Skip to content

Commit

Permalink
refactor: Simplify cookie sync manager (#963)
Browse files Browse the repository at this point in the history
  • Loading branch information
rmi22186 authored Jan 17, 2025
1 parent 61ce006 commit b28c45d
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 401 deletions.
189 changes: 74 additions & 115 deletions src/cookieSyncManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { Dictionary, isEmpty, replaceAmpWithAmpersand, replaceMPID } from './utils';
import {
Dictionary,
isEmpty,
createCookieSyncUrl,
} from './utils';
import Constants from './constants';
import { MParticleWebSDK } from './sdkRuntimeModels';
import { MPID } from '@mparticle/web-sdk';
Expand All @@ -25,7 +29,6 @@ export interface IPixelConfiguration {
}
export interface ICookieSyncManager {
attemptCookieSync: (
previousMPID: MPID,
mpid: MPID,
mpidIsNotInCookies?: boolean
) => void;
Expand All @@ -34,9 +37,6 @@ export interface ICookieSyncManager {
moduleId: string,
mpid: MPID,
cookieSyncDates: CookieSyncDates,
filteringConsentRuleValues: IConsentRules,
mpidIsNotInCookies: boolean,
requiresConsent: boolean
) => void;
combineUrlWithRedirect: (
mpid: MPID,
Expand All @@ -45,20 +45,6 @@ export interface ICookieSyncManager {
) => string;
}

const hasFrequencyCapExpired = (
frequencyCap: number,
lastSyncDate?: number,
): boolean => {
if (!lastSyncDate) {
return true;
}

return (
new Date().getTime() >
new Date(lastSyncDate).getTime() + frequencyCap * DAYS_IN_MILLISECONDS
);
}

export default function CookieSyncManager(
this: ICookieSyncManager,
mpInstance: MParticleWebSDK
Expand All @@ -67,100 +53,74 @@ export default function CookieSyncManager(

// Public
this.attemptCookieSync = (
previousMPID: MPID,
mpid: MPID,
mpidIsNotInCookies?: boolean
): void => {
if (!mpid || mpInstance._Store.webviewBridgeEnabled) {
const { pixelConfigurations, webviewBridgeEnabled } = mpInstance._Store;

if (!mpid || webviewBridgeEnabled) {
return;
}

const { pixelConfigurations } = mpInstance._Store;
const persistence = mpInstance._Persistence.getPersistence();

if (isEmpty(persistence)) {
return;
}

pixelConfigurations.forEach((pixelSettings: IPixelConfiguration) => {
// set requiresConsent to false to start each additional pixel configuration
// set to true only if filteringConsenRuleValues.values.length exists
let requiresConsent = false;

// Filtering rules as defined in UI
const { filteringConsentRuleValues } = pixelSettings;
const {
filteringConsentRuleValues,
pixelUrl,
redirectUrl,
moduleId,
// Tells you how often we should do a cookie sync (in days)
frequencyCap,
} = pixelSettings;
const { values } = filteringConsentRuleValues || {};

if (isEmpty(pixelUrl)) {
return;
}

if (!isEmpty(values)) {
requiresConsent = true;
}

// Kit Module ID
const moduleId = pixelSettings.moduleId.toString();

// Tells you how often we should do a cookie sync (in days)
const frequencyCap = pixelSettings.frequencyCap;
// If MPID is new to cookies, we should not try to perform the cookie sync
// because a cookie sync can only occur once a user either consents or doesn't.
// we should not check if it's enabled if the user has a blank consent
if (requiresConsent && mpidIsNotInCookies) {
return;
}

// Url for cookie sync pixel
const pixelUrl = replaceAmpWithAmpersand(pixelSettings.pixelUrl);
const { isEnabledForUserConsent } = mpInstance._Consent;

const redirectUrl = pixelSettings.redirectUrl
? replaceAmpWithAmpersand(pixelSettings.redirectUrl)
: null;
if (!isEnabledForUserConsent(filteringConsentRuleValues, mpInstance.Identity.getCurrentUser())) {
return;
}

const urlWithRedirect = this.combineUrlWithRedirect(
mpid,
pixelUrl,
redirectUrl
);
const cookieSyncDates: CookieSyncDates = persistence[mpid]?.csd ?? {};
const lastSyncDateForModule: number = cookieSyncDates[moduleId] || null;

if (previousMPID && previousMPID !== mpid) {
if (persistence && persistence[mpid]) {
if (!persistence[mpid].csd) {
persistence[mpid].csd = {};
}
self.performCookieSync(
urlWithRedirect,
moduleId,
mpid,
persistence[mpid].csd,
filteringConsentRuleValues,
mpidIsNotInCookies,
requiresConsent
);
}
if (!isLastSyncDateExpired(frequencyCap, lastSyncDateForModule)) {
return;
} else {
if (!persistence || !persistence[mpid]) {
return;
}

if (!persistence[mpid].csd) {
persistence[mpid].csd = {};
}

const lastSyncDateForModule = persistence[mpid].csd[moduleId] || null;

// Check to see if we need to refresh cookieSync
if (hasFrequencyCapExpired(frequencyCap, lastSyncDateForModule)) {
self.performCookieSync(
urlWithRedirect,
moduleId,
mpid,
persistence[mpid].csd,
filteringConsentRuleValues,
mpidIsNotInCookies,
requiresConsent
);
}
}
});
};

this.combineUrlWithRedirect = (
mpid: MPID,
pixelUrl: string,
redirectUrl: string,
): string => {
const url = replaceMPID(pixelUrl, mpid);
const redirect = redirectUrl ? replaceMPID(redirectUrl, mpid) : '';
return url + encodeURIComponent(redirect);
// Url for cookie sync pixel
const fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl)

self.performCookieSync(
fullUrl,
moduleId.toString(),
mpid,
cookieSyncDates
);
});
};

// Private
Expand All @@ -169,35 +129,34 @@ export default function CookieSyncManager(
moduleId: string,
mpid: MPID,
cookieSyncDates: CookieSyncDates,
filteringConsentRuleValues: IConsentRules,
mpidIsNotInCookies: boolean,
requiresConsent: boolean
): void => {
// if MPID is new to cookies, we should not try to perform the cookie sync
// because a cookie sync can only occur once a user either consents or doesn't
// we should not check if its enabled if the user has a blank consent
if (requiresConsent && mpidIsNotInCookies) {
return;
}
const img = document.createElement('img');

if (
// https://go.mparticle.com/work/SQDSDKS-5009
mpInstance._Consent.isEnabledForUserConsent(
filteringConsentRuleValues,
mpInstance.Identity.getCurrentUser()
)
) {
const img = document.createElement('img');

mpInstance.Logger.verbose(InformationMessages.CookieSync);
img.onload = function() {
cookieSyncDates[moduleId] = new Date().getTime();
mpInstance._Persistence.saveUserCookieSyncDatesToPersistence(
mpid,
cookieSyncDates
);
};
img.src = url;
}
mpInstance.Logger.verbose(InformationMessages.CookieSync);
img.onload = function() {
cookieSyncDates[moduleId] = new Date().getTime();

mpInstance._Persistence.saveUserCookieSyncDatesToPersistence(
mpid,
cookieSyncDates
);
};
img.src = url;
};
}

export const isLastSyncDateExpired = (
frequencyCap: number,
lastSyncDate?: number
): boolean => {
// If there is no lastSyncDate, then there is no previous cookie sync, so we should sync the cookie
if (!lastSyncDate) {
return true;
}

// Otherwise, compare the last sync date to determine if it should do a cookie sync again
return (
new Date().getTime() >
new Date(lastSyncDate).getTime() + frequencyCap * DAYS_IN_MILLISECONDS
);
};
6 changes: 1 addition & 5 deletions src/identity.js
Original file line number Diff line number Diff line change
Expand Up @@ -1230,10 +1230,7 @@ export default function Identity(mpInstance) {
this.getUserIdentities().userIdentities,
mpInstance._APIClient.prepareForwardingStats
);
mpInstance._CookieSyncManager.attemptCookieSync(
null,
this.getMPID()
);
mpInstance._CookieSyncManager.attemptCookieSync(this.getMPID());
},
isLoggedIn: function() {
return isLoggedIn;
Expand Down Expand Up @@ -1562,7 +1559,6 @@ export default function Identity(mpInstance) {
);

mpInstance._CookieSyncManager.attemptCookieSync(
previousMPID,
identityApiResult.mpid,
mpidIsNotInCookies
);
Expand Down
18 changes: 18 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,23 @@ const replaceMPID = (value: string, mpid: MPID): string => value.replace('%%mpid

const replaceAmpWithAmpersand = (value: string): string => value.replace(/&/g, '&');

const createCookieSyncUrl = (
mpid: MPID,
pixelUrl: string,
redirectUrl?: string
): string => {
const modifiedPixelUrl = replaceAmpWithAmpersand(pixelUrl);
const modifiedDirectUrl = redirectUrl
? replaceAmpWithAmpersand(redirectUrl)
: null;

const url = replaceMPID(modifiedPixelUrl, mpid);
const redirect = modifiedDirectUrl
? replaceMPID(modifiedDirectUrl, mpid)
: '';
return url + encodeURIComponent(redirect);
};

// FIXME: REFACTOR for V3
// only used in store.js to sanitize server-side formatting of
// booleans when checking for `isDevelopmentMode`
Expand Down Expand Up @@ -341,6 +358,7 @@ const getHref = (): string => {
export {
createCookieString,
revertCookieString,
createCookieSyncUrl,
valueof,
converted,
decoded,
Expand Down
Loading

0 comments on commit b28c45d

Please sign in to comment.