From 6272317b64798873b2dcbb4596c15c4ab0592548 Mon Sep 17 00:00:00 2001 From: Arijit Ray <35370469+itsarijitray@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:42:07 +0530 Subject: [PATCH 1/2] [STRATCONN-6704] Fix customerId hyphen stripping in Google Enhanced Conversions batch paths In performBatch methods, customerId hyphens were stripped into a local constant but settings.customerId (with hyphens) was still used in API URLs and conversionAction fields. This caused Google Ads API failures when customers entered their ID with hyphens (e.g. 123-456-7890). Fixed 6 occurrences across 4 actions: uploadClickConversion2, uploadCallConversion, uploadCallConversion2, uploadConversionAdjustment2. Added tests with hyphenated customerIds to verify the fix. Co-Authored-By: Claude Opus 4.6 --- .../__tests__/uploadCallConversion.test.ts | 37 ++++++++++ .../__tests__/uploadCallConversion2.test.ts | 42 ++++++++++++ .../__tests__/uploadClickConversion2.test.ts | 41 ++++++++++++ .../uploadConversionAdjustment2.test.ts | 67 +++++++++++++++++++ .../uploadCallConversion/index.ts | 7 +- .../uploadCallConversion2/index.ts | 9 +-- .../uploadClickConversion2/index.ts | 13 ++-- .../uploadConversionAdjustment2/index.ts | 2 +- 8 files changed, 204 insertions(+), 14 deletions(-) diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion.test.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion.test.ts index fee43b96f31..61c2721b9de 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion.test.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion.test.ts @@ -616,5 +616,42 @@ describe('GoogleEnhancedConversions', () => { expect(responses.length).toBe(1) expect(responses[0].status).toBe(201) }) + + it('strips hyphens from customerId in batch API URL', async () => { + const hyphenatedCustomerId = '123-456-7890' + const strippedCustomerId = '1234567890' + + const events: SegmentEvent[] = [ + createTestEvent({ + timestamp, + event: 'Test Event 1', + properties: { + email: 'test@gmail.com', + orderId: '1234', + total: '200', + currency: 'USD' + } + }) + ] + + nock(`https://googleads.googleapis.com/${API_VERSION}/customers/${strippedCustomerId}:uploadCallConversions`) + .post('') + .reply(201, { results: [{}] }) + + const responses = await testDestination.testBatchAction('uploadCallConversion', { + events, + mapping: { conversion_action: '12345', caller_id: '+1234567890', call_timestamp: timestamp }, + useDefaultMappings: true, + settings: { + customerId: hyphenatedCustomerId + } + }) + + expect(responses.length).toBe(1) + expect(responses[0].status).toBe(201) + + const body = JSON.parse(responses[0].options.body as string) + expect(body.conversions[0].conversionAction).toBe(`customers/${strippedCustomerId}/conversionActions/12345`) + }) }) }) diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion2.test.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion2.test.ts index 2b50ead2149..d6862074e83 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion2.test.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion2.test.ts @@ -756,5 +756,47 @@ describe('GoogleEnhancedConversions', () => { expect((e as Error).message).toBe('Unsupported Sync Mode "upsert"') } }) + + it('strips hyphens from customerId in batch API URL and conversionAction', async () => { + const hyphenatedCustomerId = '123-456-7890' + const strippedCustomerId = '1234567890' + + const events: SegmentEvent[] = [ + createTestEvent({ + timestamp, + event: 'Test Event 1', + properties: { + email: 'test1@gmail.com', + orderId: '1234', + total: '200', + currency: 'USD' + } + }) + ] + + nock(`https://googleads.googleapis.com/${API_VERSION}/customers/${strippedCustomerId}:uploadCallConversions`) + .post('') + .reply(201, { results: [{}] }) + + const responses = await testDestination.testBatchAction('uploadCallConversion2', { + events, + mapping: { + conversion_action: '12345', + caller_id: '+1234567890', + call_timestamp: timestamp, + __segment_internal_sync_mode: 'add' + }, + useDefaultMappings: true, + settings: { + customerId: hyphenatedCustomerId + } + }) + + expect(responses.length).toBe(1) + expect(responses[0].status).toBe(201) + + const body = JSON.parse(responses[0].options.body as string) + expect(body.conversions[0].conversionAction).toBe(`customers/${strippedCustomerId}/conversionActions/12345`) + }) }) }) diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadClickConversion2.test.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadClickConversion2.test.ts index d8d0befddb1..6f738bc5707 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadClickConversion2.test.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadClickConversion2.test.ts @@ -1793,5 +1793,46 @@ describe('GoogleEnhancedConversions', () => { expect(responses.length).toBe(1) expect(responses[0].status).toBe(201) }) + + it('strips hyphens from customerId in batch API URL and conversionAction', async () => { + const hyphenatedCustomerId = '123-456-7890' + const strippedCustomerId = '1234567890' + + const events: SegmentEvent[] = [ + createTestEvent({ + timestamp, + event: 'Test Event 1', + properties: { + gclid: '54321', + email: 'test1@gmail.com', + orderId: '1234', + total: '200', + currency: 'USD' + } + }) + ] + + nock(`https://googleads.googleapis.com/${API_VERSION}/customers/${strippedCustomerId}:uploadClickConversions`) + .post('') + .reply(201, { results: [{}] }) + + const responses = await testDestination.testBatchAction('uploadClickConversion2', { + events, + mapping: { + conversion_action: '12345', + __segment_internal_sync_mode: 'add' + }, + useDefaultMappings: true, + settings: { + customerId: hyphenatedCustomerId + } + }) + + expect(responses.length).toBe(1) + expect(responses[0].status).toBe(201) + + const body = JSON.parse(responses[0].options.body as string) + expect(body.conversions[0].conversionAction).toBe(`customers/${strippedCustomerId}/conversionActions/12345`) + }) }) }) diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadConversionAdjustment2.test.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadConversionAdjustment2.test.ts index c7f13a6479a..049c9dbc08e 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadConversionAdjustment2.test.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadConversionAdjustment2.test.ts @@ -1335,5 +1335,72 @@ describe('GoogleEnhancedConversions', () => { expect(e.message).toBe("Email provided doesn't seem to be in a valid format.") } }) + + it('strips hyphens from customerId in batch conversionAction', async () => { + const hyphenatedCustomerId = '123-456-7890' + const strippedCustomerId = '1234567890' + + const events: SegmentEvent[] = [ + createTestEvent({ + timestamp, + event: 'Test Event 1', + properties: { + gclid: '54321', + email: 'test1@gmail.com', + orderId: '1234', + phone: '1234567890', + firstName: 'Jane', + lastName: 'Doe', + currency: 'USD', + value: '123', + address: { + street: '123 Street SW', + city: 'San Diego', + state: 'CA', + postalCode: '982004' + } + } + }) + ] + + nock( + `https://googleads.googleapis.com/${API_VERSION}/customers/${strippedCustomerId}:uploadConversionAdjustments` + ) + .post('') + .reply(201, { results: [{}] }) + + const responses = await testDestination.testBatchAction('uploadConversionAdjustment2', { + events, + mapping: { + gclid: { + '@path': '$.properties.gclid' + }, + conversion_action: '12345', + adjustment_type: 'ENHANCEMENT', + conversion_timestamp: { + '@path': '$.timestamp' + }, + restatement_value: { + '@path': '$.properties.value' + }, + restatement_currency_code: { + '@path': '$.properties.currency' + }, + __segment_internal_sync_mode: 'add' + }, + useDefaultMappings: true, + settings: { + customerId: hyphenatedCustomerId + } + }) + + expect(responses.length).toBe(1) + expect(responses[0].status).toBe(201) + + const body = JSON.parse(responses[0].options.body as string) + expect(body.conversionAdjustments[0].conversionAction).toBe( + `customers/${strippedCustomerId}/conversionActions/12345` + ) + }) }) }) diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadCallConversion/index.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadCallConversion/index.ts index c02206bd0bd..f2bca444b4f 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadCallConversion/index.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadCallConversion/index.ts @@ -236,9 +236,10 @@ const action: ActionDefinition = { ) const response: ModifiedResponse = await request( - `https://googleads.googleapis.com/${getApiVersion(features, statsContext)}/customers/${ - settings.customerId - }:uploadCallConversions`, + `https://googleads.googleapis.com/${getApiVersion( + features, + statsContext + )}/customers/${customerId}:uploadCallConversions`, { method: 'post', headers: { diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadCallConversion2/index.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadCallConversion2/index.ts index bc9a9e52920..ab2d57b842f 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadCallConversion2/index.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadCallConversion2/index.ts @@ -218,7 +218,7 @@ const action: ActionDefinition = { const request_objects: CallConversionRequestObjectInterface[] = await Promise.all( payload.map(async (payloadItem) => { const request_object: CallConversionRequestObjectInterface = { - conversionAction: `customers/${settings.customerId}/conversionActions/${payloadItem.conversion_action}`, + conversionAction: `customers/${customerId}/conversionActions/${payloadItem.conversion_action}`, callerId: payloadItem.caller_id, callStartDateTime: convertTimestamp(payloadItem.call_timestamp), conversionDateTime: convertTimestamp(payloadItem.conversion_timestamp), @@ -257,9 +257,10 @@ const action: ActionDefinition = { ) const response: ModifiedResponse = await request( - `https://googleads.googleapis.com/${getApiVersion(features, statsContext)}/customers/${ - settings.customerId - }:uploadCallConversions`, + `https://googleads.googleapis.com/${getApiVersion( + features, + statsContext + )}/customers/${customerId}:uploadCallConversions`, { method: 'post', headers: { diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadClickConversion2/index.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadClickConversion2/index.ts index 3a46927b5f5..ccdf338eb4b 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadClickConversion2/index.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadClickConversion2/index.ts @@ -109,7 +109,7 @@ const action: ActionDefinition = { session_start_time_usec: { label: 'Session Start Time', description: - "The timestamp of when the user's session began on your website. This helps track the duration of user visits. The format should be a full ISO 8601 string. For example \"2025-11-18T08:52:17.023Z\".", + 'The timestamp of when the user\'s session began on your website. This helps track the duration of user visits. The format should be a full ISO 8601 string. For example "2025-11-18T08:52:17.023Z".', type: 'string', format: 'date-time' }, @@ -367,7 +367,7 @@ const action: ActionDefinition = { } const { session_attributes_encoded, user_ip_address } = payload - + const request_object: ClickConversionRequestObjectInterface = { conversionAction: `customers/${settings.customerId}/conversionActions/${payload.conversion_action}`, conversionDateTime: convertTimestamp(payload.conversion_timestamp), @@ -486,7 +486,7 @@ const action: ActionDefinition = { const { session_attributes_encoded, user_ip_address } = payloadItem const request_object: ClickConversionRequestObjectInterface = { - conversionAction: `customers/${settings.customerId}/conversionActions/${payloadItem.conversion_action}`, + conversionAction: `customers/${customerId}/conversionActions/${payloadItem.conversion_action}`, conversionDateTime: convertTimestamp(payloadItem.conversion_timestamp), gclid: payloadItem.gclid, gbraid: payloadItem.gbraid, @@ -559,9 +559,10 @@ const action: ActionDefinition = { ) const response: ModifiedResponse = await request( - `https://googleads.googleapis.com/${getApiVersion(features, statsContext)}/customers/${ - settings.customerId - }:uploadClickConversions`, + `https://googleads.googleapis.com/${getApiVersion( + features, + statsContext + )}/customers/${customerId}:uploadClickConversions`, { method: 'post', headers: { diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadConversionAdjustment2/index.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadConversionAdjustment2/index.ts index efacfd38c26..38ddfe851de 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadConversionAdjustment2/index.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/uploadConversionAdjustment2/index.ts @@ -392,7 +392,7 @@ const action: ActionDefinition = { } const request_object: ConversionAdjustmentRequestObjectInterface = { - conversionAction: `customers/${settings.customerId}/conversionActions/${payloadItem.conversion_action}`, + conversionAction: `customers/${customerId}/conversionActions/${payloadItem.conversion_action}`, adjustmentType: payloadItem.adjustment_type, adjustmentDateTime: convertTimestamp(payloadItem.adjustment_timestamp), orderId: payloadItem.order_id, From 33df8c586932592d13e7273dc146e59d09a726a4 Mon Sep 17 00:00:00 2001 From: Arijit Ray <35370469+itsarijitray@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:49:31 +0530 Subject: [PATCH 2/2] Rename test names to reflect both API URL and conversionAction coverage Addresses Copilot review comments on PR #3747. Co-Authored-By: Claude Opus 4.6 --- .../__tests__/uploadCallConversion.test.ts | 2 +- .../__tests__/uploadConversionAdjustment2.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion.test.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion.test.ts index 61c2721b9de..55f457eb334 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion.test.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadCallConversion.test.ts @@ -617,7 +617,7 @@ describe('GoogleEnhancedConversions', () => { expect(responses[0].status).toBe(201) }) - it('strips hyphens from customerId in batch API URL', async () => { + it('strips hyphens from customerId in batch API URL and conversionAction', async () => { const hyphenatedCustomerId = '123-456-7890' const strippedCustomerId = '1234567890' diff --git a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadConversionAdjustment2.test.ts b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadConversionAdjustment2.test.ts index 049c9dbc08e..b8d26a284a1 100644 --- a/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadConversionAdjustment2.test.ts +++ b/packages/destination-actions/src/destinations/google-enhanced-conversions/__tests__/uploadConversionAdjustment2.test.ts @@ -1336,7 +1336,7 @@ describe('GoogleEnhancedConversions', () => { } }) - it('strips hyphens from customerId in batch conversionAction', async () => { + it('strips hyphens from customerId in batch API URL and conversionAction', async () => { const hyphenatedCustomerId = '123-456-7890' const strippedCustomerId = '1234567890'