Skip to content

Commit 0fe7403

Browse files
rmi22186claude
andcommitted
feat: Add base64-encoded MPID query parameter for Google Marketing Platform cookie sync
When the cookie sync partner is DoubleclickDFP (module ID 41), append a `google_hm` query parameter containing the base64-encoded MPID to the cookie sync URL. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 138d7c4 commit 0fe7403

3 files changed

Lines changed: 102 additions & 7 deletions

File tree

src/cookieSyncManager.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,11 @@ export default function CookieSyncManager(
137137
// It is optional but to simplify the code, we add it for all Trade
138138
// // Desk cookie syncs.
139139
const domain = moduleId === PARTNER_MODULE_IDS.TradeDesk ? window.location.hostname : undefined;
140-
// Add domain parameter for Trade Desk
141-
const fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain);
140+
141+
// Google Marketing Platform requires a base64-encoded MPID query parameter
142+
const base64Mpid = moduleId === PARTNER_MODULE_IDS.DoubleclickDFP ? btoa(mpid) : undefined;
143+
144+
const fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl, domain, base64Mpid);
142145

143146
self.performCookieSync(
144147
fullUrl,

src/utils.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,26 +207,32 @@ const createCookieSyncUrl = (
207207
mpid: MPID,
208208
pixelUrl: string,
209209
redirectUrl?: string,
210-
domain?: string
210+
domain?: string,
211+
base64Mpid?: string
211212
): string => {
212213
const modifiedPixelUrl = replaceAmpWithAmpersand(pixelUrl);
213214
const modifiedDirectUrl = redirectUrl
214215
? replaceAmpWithAmpersand(redirectUrl)
215216
: null;
216217

217218
let url = replaceMPID(modifiedPixelUrl, mpid);
218-
219+
219220
const redirect = modifiedDirectUrl
220221
? replaceMPID(modifiedDirectUrl, mpid)
221222
: '';
222-
223+
223224
let fullUrl = url + encodeURIComponent(redirect);
224-
225+
225226
if (domain) {
226227
const separator = fullUrl.includes('?') ? '&' : '?';
227228
fullUrl += `${separator}domain=${domain}`;
228229
}
229-
230+
231+
if (base64Mpid) {
232+
const separator = fullUrl.includes('?') ? '&' : '?';
233+
fullUrl += `${separator}google_hm=${base64Mpid}`;
234+
}
235+
230236
return fullUrl;
231237
};
232238

test/jest/cookieSyncManager.spec.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,92 @@ describe('CookieSyncManager', () => {
776776
);
777777
});
778778
});
779+
780+
describe('Google Marketing Platform (DoubleclickDFP) base64 MPID', () => {
781+
it('should add base64-encoded MPID parameter for DoubleclickDFP (module ID 41)', () => {
782+
const gmpPixelSettings: IPixelConfiguration = {
783+
...pixelSettings,
784+
moduleId: PARTNER_MODULE_IDS.DoubleclickDFP, // 41
785+
pixelUrl: 'https://cm.g.doubleclick.net/pixel?google_nid=abc123',
786+
redirectUrl: '',
787+
};
788+
789+
const mockMPInstance = ({
790+
_Store: {
791+
webviewBridgeEnabled: false,
792+
pixelConfigurations: [gmpPixelSettings],
793+
},
794+
_CookieConsentManager: { getNoFunctional: jest.fn().mockReturnValue(false) },
795+
_Persistence: {
796+
getPersistence: () => ({testMPID: {
797+
csd: {}
798+
}}),
799+
},
800+
_Consent: {
801+
isEnabledForUserConsent: jest.fn().mockReturnValue(true),
802+
},
803+
Identity: {
804+
getCurrentUser: jest.fn().mockReturnValue({
805+
getMPID: () => testMPID,
806+
}),
807+
},
808+
} as unknown) as IMParticleWebSDKInstance;
809+
810+
const cookieSyncManager = new CookieSyncManager(mockMPInstance);
811+
cookieSyncManager.performCookieSync = jest.fn();
812+
813+
cookieSyncManager.attemptCookieSync(testMPID, true);
814+
815+
expect(cookieSyncManager.performCookieSync).toHaveBeenCalledWith(
816+
`https://cm.g.doubleclick.net/pixel?google_nid=abc123&google_hm=${btoa(testMPID)}`,
817+
'41',
818+
testMPID,
819+
{},
820+
);
821+
});
822+
823+
it('should not add base64 MPID parameter for non-DoubleclickDFP partners', () => {
824+
const appNexusPixelSettings: IPixelConfiguration = {
825+
...pixelSettings,
826+
moduleId: PARTNER_MODULE_IDS.AppNexus, // 50
827+
pixelUrl: 'https://ib.adnxs.com/cookie_sync?adv=abc123',
828+
redirectUrl: '',
829+
};
830+
831+
const mockMPInstance = ({
832+
_Store: {
833+
webviewBridgeEnabled: false,
834+
pixelConfigurations: [appNexusPixelSettings],
835+
},
836+
_CookieConsentManager: { getNoFunctional: jest.fn().mockReturnValue(false) },
837+
_Persistence: {
838+
getPersistence: () => ({testMPID: {
839+
csd: {}
840+
}}),
841+
},
842+
_Consent: {
843+
isEnabledForUserConsent: jest.fn().mockReturnValue(true),
844+
},
845+
Identity: {
846+
getCurrentUser: jest.fn().mockReturnValue({
847+
getMPID: () => testMPID,
848+
}),
849+
},
850+
} as unknown) as IMParticleWebSDKInstance;
851+
852+
const cookieSyncManager = new CookieSyncManager(mockMPInstance);
853+
cookieSyncManager.performCookieSync = jest.fn();
854+
855+
cookieSyncManager.attemptCookieSync(testMPID, true);
856+
857+
expect(cookieSyncManager.performCookieSync).toHaveBeenCalledWith(
858+
'https://ib.adnxs.com/cookie_sync?adv=abc123',
859+
'50',
860+
testMPID,
861+
{},
862+
);
863+
});
864+
});
779865
});
780866

781867
describe('PARTNER_MODULE_IDS', () => {

0 commit comments

Comments
 (0)