Skip to content

Commit 7f57e45

Browse files
chore: add campaign object support in web pixel events (#3973)
* chore: add campaign object support in web pixel events * chore: add custom utm support
1 parent e285d8b commit 7f57e45

File tree

4 files changed

+176
-35
lines changed

4 files changed

+176
-35
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[
2+
{
3+
"sourceKeys": "utm_campaign",
4+
"destKeys": "name"
5+
},
6+
{
7+
"sourceKeys": "utm_medium",
8+
"destKeys": "medium"
9+
},
10+
{
11+
"sourceKeys": "utm_term",
12+
"destKeys": "term"
13+
},
14+
{
15+
"sourceKeys": "utm_content",
16+
"destKeys": "content"
17+
}
18+
]

src/v1/sources/shopify/webpixelTransformations/pixelTransform.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const {
1616
checkoutStepEventBuilder,
1717
searchEventBuilder,
1818
} = require('./pixelUtils');
19+
const campaignObjectMappings = require('../pixelEventsMappings/campaignObjectMappings.json');
1920
const {
2021
INTEGERATION,
2122
PIXEL_EVENT_TOPICS,
@@ -85,7 +86,7 @@ const handleCartTokenRedisOperations = async (inputEvent, clientId) => {
8586

8687
function processPixelEvent(inputEvent) {
8788
// eslint-disable-next-line @typescript-eslint/naming-convention
88-
const { name, query_parameters, clientId, data, id } = inputEvent;
89+
const { name, query_parameters, context, clientId, data, id } = inputEvent;
8990
const shopifyDetails = { ...inputEvent };
9091
delete shopifyDetails.context;
9192
delete shopifyDetails.query_parameters;
@@ -147,6 +148,36 @@ function processPixelEvent(inputEvent) {
147148
});
148149
message.setProperty('context.topic', name);
149150
message.setProperty('context.shopifyDetails', shopifyDetails);
151+
152+
// adding campaign object to the message
153+
if (context?.document?.location?.href) {
154+
const url = new URL(context.document.location.href);
155+
const campaignParams = {};
156+
157+
// Loop through mappings and extract UTM parameters
158+
campaignObjectMappings.forEach((mapping) => {
159+
const value = url.searchParams.get(mapping.sourceKeys);
160+
if (value) {
161+
campaignParams[mapping.destKeys] = value;
162+
}
163+
});
164+
165+
// Extract any UTM parameters not in the mappings
166+
const campaignObjectSourceKeys = campaignObjectMappings.flatMap(
167+
(mapping) => mapping.sourceKeys,
168+
);
169+
url.searchParams.forEach((value, key) => {
170+
if (key.startsWith('utm_') && !campaignObjectSourceKeys.includes(key)) {
171+
campaignParams[key] = value;
172+
}
173+
});
174+
175+
// Only add campaign object if we have any UTM parameters
176+
if (Object.keys(campaignParams).length > 0) {
177+
message.context = message.context || {};
178+
message.context.campaign = campaignParams;
179+
}
180+
}
150181
message.messageId = id;
151182
message = removeUndefinedAndNullValues(message);
152183
return message;

test/integrations/sources/shopify/constants.ts

Lines changed: 110 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,58 @@
1+
const dummyResponseCommonPayload = {
2+
navigator: {
3+
language: 'en-US',
4+
cookieEnabled: true,
5+
languages: ['en-US', 'en'],
6+
userAgent:
7+
'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',
8+
},
9+
window: {
10+
innerHeight: 1028,
11+
innerWidth: 1362,
12+
outerHeight: 1080,
13+
outerWidth: 1728,
14+
pageXOffset: 0,
15+
pageYOffset: 0,
16+
location: {
17+
href: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
18+
hash: '',
19+
host: 'store.myshopify.com',
20+
hostname: 'store.myshopify.com',
21+
origin: 'https://store.myshopify.com',
22+
pathname: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
23+
port: '',
24+
protocol: 'https:',
25+
search: '',
26+
},
27+
origin: 'https://store.myshopify.com',
28+
screen: {
29+
height: 1117,
30+
width: 1728,
31+
},
32+
screenX: 0,
33+
screenY: 37,
34+
scrollX: 0,
35+
scrollY: 0,
36+
},
37+
page: {
38+
title: 'Checkout - pixel-testing-rs',
39+
url: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
40+
path: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
41+
search: '',
42+
},
43+
userAgent:
44+
'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',
45+
screen: {
46+
height: 1117,
47+
width: 1728,
48+
},
49+
library: {
50+
name: 'RudderStack Shopify Cloud',
51+
eventOrigin: 'client',
52+
version: '2.0.0',
53+
},
54+
};
55+
156
export const dummySourceConfig = {
257
ID: 'dummy-source-id',
358
OriginalID: '',
@@ -83,25 +138,10 @@ export const dummyContext = {
83138
},
84139
};
85140

86-
export const note_attributes = [
87-
{
88-
name: 'cartId',
89-
value: '9c623f099fc8819aa4d6a958b65dfe7d',
90-
},
91-
{
92-
name: 'cartToken',
93-
value: 'Z2NwLXVzLWVhc3QxOjAxSkQzNUFXVEI4VkVUNUpTTk1LSzBCMzlF',
94-
},
95-
{
96-
name: 'rudderAnonymousId',
97-
value: '50ead33e-d763-4854-b0ab-765859ef05cb',
98-
},
99-
];
100-
101-
export const responseDummyContext = {
141+
export const dummyContextwithCampaign = {
102142
document: {
103143
location: {
104-
href: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
144+
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&utm_custom1=customutm&tag=tag',
105145
hash: '',
106146
host: 'store.myshopify.com',
107147
hostname: 'store.myshopify.com',
@@ -150,21 +190,60 @@ export const responseDummyContext = {
150190
scrollX: 0,
151191
scrollY: 0,
152192
},
153-
page: {
154-
title: 'Checkout - pixel-testing-rs',
155-
url: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
156-
path: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
157-
search: '',
193+
};
194+
195+
export const note_attributes = [
196+
{
197+
name: 'cartId',
198+
value: '9c623f099fc8819aa4d6a958b65dfe7d',
158199
},
159-
userAgent:
160-
'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',
161-
screen: {
162-
height: 1117,
163-
width: 1728,
200+
{
201+
name: 'cartToken',
202+
value: 'Z2NwLXVzLWVhc3QxOjAxSkQzNUFXVEI4VkVUNUpTTk1LSzBCMzlF',
164203
},
165-
library: {
166-
name: 'RudderStack Shopify Cloud',
167-
eventOrigin: 'client',
168-
version: '2.0.0',
204+
{
205+
name: 'rudderAnonymousId',
206+
value: '50ead33e-d763-4854-b0ab-765859ef05cb',
207+
},
208+
];
209+
210+
export const responseDummyContext = {
211+
document: {
212+
location: {
213+
href: 'https://store.myshopify.com/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
214+
hash: '',
215+
host: 'store.myshopify.com',
216+
hostname: 'store.myshopify.com',
217+
origin: 'https://store.myshopify.com',
218+
pathname: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
219+
port: '',
220+
protocol: 'https:',
221+
search: '',
222+
},
223+
referrer: 'https://store.myshopify.com/cart',
224+
characterSet: 'UTF-8',
225+
title: 'Checkout - pixel-testing-rs',
226+
},
227+
...dummyResponseCommonPayload,
228+
};
229+
230+
export const responseDummyContextwithCampaign = {
231+
document: {
232+
location: {
233+
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&utm_custom1=customutm&tag=tag',
234+
hash: '',
235+
host: 'store.myshopify.com',
236+
hostname: 'store.myshopify.com',
237+
origin: 'https://store.myshopify.com',
238+
pathname: '/checkouts/cn/Z2NwLXVzLWVhc3QxOjAxSjY5OVpIRURQNERFMDBKUTVaRkI4UzdU',
239+
port: '',
240+
protocol: 'https:',
241+
search: '',
242+
},
243+
referrer: 'https://store.myshopify.com/cart',
244+
title: 'Checkout - pixel-testing-rs',
245+
characterSet: 'UTF-8',
169246
},
247+
// title: 'Checkout - pixel-testing-rs',
248+
...dummyResponseCommonPayload,
170249
};

test/integrations/sources/shopify/pixelTestScenarios/ProductEventsTests.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
// This file contains the test scenarios related to Shopify pixel events, emitted from web pixel on the browser.
2-
import { dummyContext, dummySourceConfig, responseDummyContext } from '../constants';
2+
import {
3+
dummyContext,
4+
dummyContextwithCampaign,
5+
dummySourceConfig,
6+
responseDummyContext,
7+
responseDummyContextwithCampaign,
8+
} from '../constants';
39

410
export const pixelEventsTestScenarios = [
511
{
@@ -18,7 +24,7 @@ export const pixelEventsTestScenarios = [
1824
type: 'standard',
1925
clientId: 'c7b3f99b-4d34-463b-835f-c879482a7750',
2026
timestamp: '2024-09-15T17:24:30.373Z',
21-
context: dummyContext,
27+
context: dummyContextwithCampaign,
2228
pixelEventLabel: true,
2329
query_parameters: {
2430
topic: ['page_viewed'],
@@ -42,7 +48,14 @@ export const pixelEventsTestScenarios = [
4248
batch: [
4349
{
4450
context: {
45-
...responseDummyContext,
51+
...responseDummyContextwithCampaign,
52+
campaign: {
53+
content: 'web',
54+
medium: 'checkout',
55+
name: 'shopifySale',
56+
term: 'term_checkout',
57+
utm_custom1: 'customutm',
58+
},
4659
shopifyDetails: {
4760
clientId: 'c7b3f99b-4d34-463b-835f-c879482a7750',
4861
data: {},

0 commit comments

Comments
 (0)