Commit 0b34aab6178 for woocommerce
commit 0b34aab61784732e1ea2c86f3725b11affeecea6
Author: Justin P <228780+layoutd@users.noreply.github.com>
Date: Tue Aug 18 10:42:32 2026 +0200
Preserve checkout attribution inputs during deduplication (#67711)
* Preserve checkout attribution inputs during deduplication
* Add changelog entry for order attribution deduplication fix
* Add checkout form precedence regression coverage
* Fix order attribution deduplication per form
* Add changefile(s) from automation for the following project(s): woocommerce
---------
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/67711-fix-order-attribution-form-dedup b/plugins/woocommerce/changelog/67711-fix-order-attribution-form-dedup
new file mode 100644
index 00000000000..2d18b94784e
--- /dev/null
+++ b/plugins/woocommerce/changelog/67711-fix-order-attribution-form-dedup
@@ -0,0 +1,5 @@
+Significance: patch
+Type: fix
+Comment: Select if this PR needs a generated summary for release notes: - [ ] **Feature Highlight** - For user-facing features (what changed, user impact) - [ ] **Developer Advisory** - For developer-facing changes (what changed, how to detect, actions needed) <details> <summary>When to use each?</summary> **Feature Highlight**: New features, UI changes, or improvements that merchants/store owners will notice. - Example: "New bulk editing for products", "Improved checkout performance" **Developer Advisory**: Breaking changes, deprecations, or changes that affect themes/plugins/extensions. - Example: "Hook signature change", "Deprecated filter", "REST API field removed" An AI will analyze your PR and post a draft comment for you to review and edit.
+
+
diff --git a/plugins/woocommerce/changelog/fix-order-attribution-form-dedup b/plugins/woocommerce/changelog/fix-order-attribution-form-dedup
new file mode 100644
index 00000000000..cc10b2ca22d
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-order-attribution-form-dedup
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Preserve classic checkout order attribution when duplicate input groups exist outside the checkout form.
diff --git a/plugins/woocommerce/client/legacy/js/frontend/order-attribution.js b/plugins/woocommerce/client/legacy/js/frontend/order-attribution.js
index c409b0599ef..d307803d559 100644
--- a/plugins/woocommerce/client/legacy/js/frontend/order-attribution.js
+++ b/plugins/woocommerce/client/legacy/js/frontend/order-attribution.js
@@ -28,13 +28,19 @@
}
/**
- * Remove duplicate `<wc-order-attribution-inputs>` elements, leaving only the first one,
- * to prevent sending the same data multiple times.
+ * Remove duplicate `<wc-order-attribution-inputs>` elements within each owning form to prevent
+ * sending the same data multiple times. Treat groups without an enclosing form as document-owned.
*/
function removeDuplicateInputGroups() {
- document.querySelectorAll( 'wc-order-attribution-inputs' ).forEach( ( group, index ) => {
- if ( index > 0 ) {
+ const owners = new Set();
+
+ document.querySelectorAll( 'wc-order-attribution-inputs' ).forEach( ( group ) => {
+ const owner = group.closest( 'form' ) || document;
+
+ if ( owners.has( owner ) ) {
group.remove();
+ } else {
+ owners.add( owner );
}
} );
}
diff --git a/plugins/woocommerce/client/legacy/js/frontend/test/order-attribution.js b/plugins/woocommerce/client/legacy/js/frontend/test/order-attribution.js
new file mode 100644
index 00000000000..3c4c4834b66
--- /dev/null
+++ b/plugins/woocommerce/client/legacy/js/frontend/test/order-attribution.js
@@ -0,0 +1,96 @@
+/**
+ * @jest-environment jest-fixed-jsdom
+ */
+
+describe( 'Order attribution input deduplication', () => {
+ beforeAll( () => {
+ window.wc_order_attribution = {
+ fields: {
+ source_type: 'current.typ',
+ },
+ params: {
+ allowTracking: false,
+ prefix: 'wc_order_attribution_',
+ },
+ };
+
+ require( '../order-attribution' );
+ } );
+
+ beforeEach( () => {
+ document.body.innerHTML = '';
+ } );
+
+ afterAll( () => {
+ delete window.wc_order_attribution;
+ } );
+
+ test( 'keeps checkout attribution when an out-of-form group appears first', () => {
+ document.body.innerHTML = `
+ <wc-order-attribution-inputs id="outside-form"></wc-order-attribution-inputs>
+ <form name="checkout">
+ <wc-order-attribution-inputs id="checkout-first"></wc-order-attribution-inputs>
+ <wc-order-attribution-inputs id="checkout-second"></wc-order-attribution-inputs>
+ </form>
+ `;
+
+ window.wc_order_attribution.setOrderTracking( false );
+
+ expect(
+ document.querySelectorAll( 'wc-order-attribution-inputs' )
+ ).toHaveLength( 2 );
+ expect( document.getElementById( 'checkout-first' ) ).not.toBeNull();
+ expect( document.getElementById( 'outside-form' ) ).not.toBeNull();
+ expect( document.getElementById( 'checkout-second' ) ).toBeNull();
+ expect(
+ document.querySelector( 'form[name="checkout"]' ).elements.namedItem(
+ 'wc_order_attribution_source_type'
+ )
+ ).not.toBeNull();
+ } );
+
+ test( 'keeps one group in each form', () => {
+ document.body.innerHTML = `
+ <form name="register">
+ <wc-order-attribution-inputs id="register-first"></wc-order-attribution-inputs>
+ <wc-order-attribution-inputs id="register-second"></wc-order-attribution-inputs>
+ </form>
+ <form name="checkout">
+ <wc-order-attribution-inputs id="checkout-first"></wc-order-attribution-inputs>
+ <wc-order-attribution-inputs id="checkout-second"></wc-order-attribution-inputs>
+ </form>
+ `;
+
+ window.wc_order_attribution.setOrderTracking( false );
+
+ expect(
+ document.querySelectorAll( 'wc-order-attribution-inputs' )
+ ).toHaveLength( 2 );
+ expect( document.getElementById( 'register-first' ) ).not.toBeNull();
+ expect( document.getElementById( 'register-second' ) ).toBeNull();
+ expect( document.getElementById( 'checkout-first' ) ).not.toBeNull();
+ expect( document.getElementById( 'checkout-second' ) ).toBeNull();
+ expect(
+ document.querySelector( 'form[name="register"]' ).elements.namedItem(
+ 'wc_order_attribution_source_type'
+ )
+ ).not.toBeNull();
+ expect(
+ document.querySelector( 'form[name="checkout"]' ).elements.namedItem(
+ 'wc_order_attribution_source_type'
+ )
+ ).not.toBeNull();
+ } );
+
+ test( 'keeps the first document-owned group', () => {
+ document.body.innerHTML = `
+ <wc-order-attribution-inputs id="first"></wc-order-attribution-inputs>
+ <wc-order-attribution-inputs id="second"></wc-order-attribution-inputs>
+ `;
+
+ window.wc_order_attribution.setOrderTracking( false );
+
+ expect( document.getElementById( 'first' ) ).not.toBeNull();
+ expect( document.getElementById( 'second' ) ).toBeNull();
+ } );
+} );