diff --git a/src/v1/sources/shopify/pixelEventsMappings/campaignObjectMappings.json b/src/v1/sources/shopify/pixelEventsMappings/campaignObjectMappings.json new file mode 100644 index 0000000000..319502e377 --- /dev/null +++ b/src/v1/sources/shopify/pixelEventsMappings/campaignObjectMappings.json @@ -0,0 +1,18 @@ +[ + { + "sourceKeys": "utm_campaign", + "destKeys": "name" + }, + { + "sourceKeys": "utm_medium", + "destKeys": "medium" + }, + { + "sourceKeys": "utm_term", + "destKeys": "term" + }, + { + "sourceKeys": "utm_content", + "destKeys": "content" + } +] diff --git a/src/v1/sources/shopify/webpixelTransformations/pixelTransform.js b/src/v1/sources/shopify/webpixelTransformations/pixelTransform.js index b1d1c8b2fa..0ff7f48c47 100644 --- a/src/v1/sources/shopify/webpixelTransformations/pixelTransform.js +++ b/src/v1/sources/shopify/webpixelTransformations/pixelTransform.js @@ -16,6 +16,7 @@ const { checkoutStepEventBuilder, searchEventBuilder, } = require('./pixelUtils'); +const campaignObjectMappings = require('../pixelEventsMappings/campaignObjectMappings.json'); const { INTEGERATION, PIXEL_EVENT_TOPICS, @@ -85,7 +86,7 @@ const handleCartTokenRedisOperations = async (inputEvent, clientId) => { function processPixelEvent(inputEvent) { // eslint-disable-next-line @typescript-eslint/naming-convention - const { name, query_parameters, clientId, data, id } = inputEvent; + const { name, query_parameters, context, clientId, data, id } = inputEvent; const shopifyDetails = { ...inputEvent }; delete shopifyDetails.context; delete shopifyDetails.query_parameters; @@ -147,6 +148,26 @@ function processPixelEvent(inputEvent) { }); message.setProperty('context.topic', name); message.setProperty('context.shopifyDetails', shopifyDetails); + + // adding campaign object to the message + if (context?.document?.location?.href) { + const url = new URL(context.document.location.href); + const campaignParams = {}; + + // Loop through mappings and extract UTM parameters + campaignObjectMappings.forEach((mapping) => { + const value = url.searchParams.get(mapping.sourceKeys); + if (value) { + campaignParams[mapping.destKeys] = value; + } + }); + + // Only add campaign object if we have any UTM parameters + if (Object.keys(campaignParams).length > 0) { + message.context = message.context || {}; + message.context.campaign = campaignParams; + } + } message.messageId = id; message = removeUndefinedAndNullValues(message); return message; diff --git a/test/integrations/sources/shopify/constants.ts b/test/integrations/sources/shopify/constants.ts index af53a3180e..456613328d 100644 --- a/test/integrations/sources/shopify/constants.ts +++ b/test/integrations/sources/shopify/constants.ts @@ -1,3 +1,58 @@ +const dummyResponseCommonPayload = { + navigator: { + language: 'en-US', + cookieEnabled: true, + languages: ['en-US', 'en'], + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', + }, + window: { + innerHeight: 1028, + innerWidth: 1362, + outerHeight: 1080, + outerWidth: 1728, + pageXOffset: 0, + pageYOffset: 0, + location: { + href: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', + hash: '', + host: 'store.myshopify.com', + hostname: 'store.myshopify.com', + origin: 'https://store.myshopify.com', + pathname: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', + port: '', + protocol: 'https:', + search: '', + }, + origin: 'https://store.myshopify.com', + screen: { + height: 1117, + width: 1728, + }, + screenX: 0, + screenY: 37, + scrollX: 0, + scrollY: 0, + }, + page: { + title: 'Checkout - pixel-testing-rs', + url: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', + path: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', + search: '', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', + screen: { + height: 1117, + width: 1728, + }, + library: { + name: 'RudderStack Shopify Cloud', + eventOrigin: 'client', + version: '2.0.0', + }, +}; + export const dummySourceConfig = { ID: 'dummy-source-id', OriginalID: '', @@ -83,25 +138,10 @@ export const dummyContext = { }, }; -export const note_attributes = [ - { - name: 'cartId', - value: '9c623f099fc8819aa4d6a958b65dfe7d', - }, - { - name: 'cartToken', - value: 'Z2NwLXVzLWVhc3QxOjAxSkQzNUFXVEI4VkVUNUpTTk1LSzBCMzlF', - }, - { - name: 'rudderAnonymousId', - value: '50ead33e-d763-4854-b0ab-765859ef05cb', - }, -]; - -export const responseDummyContext = { +export const dummyContextwithCampaign = { document: { location: { - href: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', + href: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU?checkout%5Bpayment_gateway%5D=shopify_payments&utm_campaign=shopifySale&utm_medium=checkout&utm_term=term_checkout&utm_content=web', hash: '', host: 'store.myshopify.com', hostname: 'store.myshopify.com', @@ -150,21 +190,60 @@ export const responseDummyContext = { scrollX: 0, scrollY: 0, }, - page: { - title: 'Checkout - pixel-testing-rs', - url: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', - path: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', - search: '', +}; + +export const note_attributes = [ + { + name: 'cartId', + value: '9c623f099fc8819aa4d6a958b65dfe7d', }, - userAgent: - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', - screen: { - height: 1117, - width: 1728, + { + name: 'cartToken', + value: 'Z2NwLXVzLWVhc3QxOjAxSkQzNUFXVEI4VkVUNUpTTk1LSzBCMzlF', }, - library: { - name: 'RudderStack Shopify Cloud', - eventOrigin: 'client', - version: '2.0.0', + { + name: 'rudderAnonymousId', + value: '50ead33e-d763-4854-b0ab-765859ef05cb', + }, +]; + +export const responseDummyContext = { + document: { + location: { + href: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', + hash: '', + host: 'store.myshopify.com', + hostname: 'store.myshopify.com', + origin: 'https://store.myshopify.com', + pathname: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', + port: '', + protocol: 'https:', + search: '', + }, + referrer: 'https://store.myshopify.com/cart', + characterSet: 'UTF-8', + title: 'Checkout - pixel-testing-rs', + }, + ...dummyResponseCommonPayload, +}; + +export const responseDummyContextwithCampaign = { + document: { + location: { + href: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU?checkout%5Bpayment_gateway%5D=shopify_payments&utm_campaign=shopifySale&utm_medium=checkout&utm_term=term_checkout&utm_content=web', + hash: '', + host: 'store.myshopify.com', + hostname: 'store.myshopify.com', + origin: 'https://store.myshopify.com', + pathname: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU', + port: '', + protocol: 'https:', + search: '', + }, + referrer: 'https://store.myshopify.com/cart', + title: 'Checkout - pixel-testing-rs', + characterSet: 'UTF-8', }, + // title: 'Checkout - pixel-testing-rs', + ...dummyResponseCommonPayload, }; diff --git a/test/integrations/sources/shopify/pixelTestScenarios/ProductEventsTests.ts b/test/integrations/sources/shopify/pixelTestScenarios/ProductEventsTests.ts index 46bd4f9615..c0789ea341 100644 --- a/test/integrations/sources/shopify/pixelTestScenarios/ProductEventsTests.ts +++ b/test/integrations/sources/shopify/pixelTestScenarios/ProductEventsTests.ts @@ -1,5 +1,11 @@ // This file contains the test scenarios related to Shopify pixel events, emitted from web pixel on the browser. -import { dummyContext, dummySourceConfig, responseDummyContext } from '../constants'; +import { + dummyContext, + dummyContextwithCampaign, + dummySourceConfig, + responseDummyContext, + responseDummyContextwithCampaign, +} from '../constants'; export const pixelEventsTestScenarios = [ { @@ -18,7 +24,7 @@ export const pixelEventsTestScenarios = [ type: 'standard', clientId: 'c7b3f99b-4d34-463b-835f-c879482a7750', timestamp: '2024-09-15T17:24:30.373Z', - context: dummyContext, + context: dummyContextwithCampaign, pixelEventLabel: true, query_parameters: { topic: ['page_viewed'], @@ -42,7 +48,13 @@ export const pixelEventsTestScenarios = [ batch: [ { context: { - ...responseDummyContext, + ...responseDummyContextwithCampaign, + campaign: { + content: 'web', + medium: 'checkout', + name: 'shopifySale', + term: 'term_checkout', + }, shopifyDetails: { clientId: 'c7b3f99b-4d34-463b-835f-c879482a7750', data: {},