Merge pull request #1961 from Safelite/feature/Digital/CSR-1629
CSR-1629
This commit is contained in:
commit
af55ada8e9
5 changed files with 134 additions and 3 deletions
|
|
@ -31,6 +31,7 @@ const applicationConfig = {
|
|||
"https://outlook.office.com/calendar/deeplink/compose?path=/calendar/action/compose&rru=addevent",
|
||||
FRONTEND_LOGGER_PATH: "/analytics/api/v1/logging",
|
||||
AFFILIATE_COOKIE_CONTAINING_NAME: "_Track",
|
||||
COOKIE_NAME_LENGTH_MAX_LIMIT: 44,
|
||||
};
|
||||
|
||||
export { applicationConfig };
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ const cookieNames = {
|
|||
DXDEV: "dxdev",
|
||||
SESSION_ID: "sid",
|
||||
SESSION_KEY: "skey",
|
||||
|
||||
//Commission Junction Cookie
|
||||
CJE: "cje",
|
||||
};
|
||||
|
||||
const cookieExpirations = {
|
||||
|
|
@ -17,6 +20,8 @@ const cookieExpirations = {
|
|||
DXDEV: convertToSeconds({ years: 1 }),
|
||||
FUNNEL_USER_ID: convertToSeconds({ weeks: 1 }),
|
||||
FUNNEL_SESSION_KEY: convertToSeconds({ minutes: 30 }),
|
||||
CJE: convertToSeconds({ days: 395 }),
|
||||
NON_CJ: convertToSeconds({ days: 100000 }),
|
||||
};
|
||||
|
||||
export { cookieNames, cookieExpirations };
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ const queryStrings = {
|
|||
VIN_SELECTION: "vinselection",
|
||||
SERVICE_PACKAGE: "servicepackage",
|
||||
NUMBER_OF_CHIPS: "numberofchips",
|
||||
UTM_SOURCE: "_source",
|
||||
UTM_MEDIUM: "_medium",
|
||||
UTM_CAMPAIGN: "_campaign",
|
||||
CJ_EVENT: "cjevent",
|
||||
CJUNCTION: "cjunction",
|
||||
ORGANIC: "organic",
|
||||
ORGANIC_SOCIAL: "organic_social",
|
||||
};
|
||||
|
||||
export { queryStrings };
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import { cookieNames, cookieExpirations } from "@/constants/cookie-names";
|
||||
import store from "@/store";
|
||||
import { applicationConfig } from "@/constants/application-config";
|
||||
|
||||
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
//import { cookieParameters } from "@/constants/cookie-parameters";
|
||||
/*
|
||||
Will update the cookie if present, or create a new one if not.
|
||||
*/
|
||||
|
|
@ -221,6 +223,79 @@ export function getAffiliateCookies() {
|
|||
return affiliateCookies;
|
||||
}
|
||||
|
||||
export function setupAdvertiserTracking() {
|
||||
var utmSource = getQuerystringParameter(queryStrings.UTM_SOURCE);
|
||||
var utmMedium = getQuerystringParameter(queryStrings.UTM_MEDIUM);
|
||||
var utmCampaign = getQuerystringParameter(queryStrings.UTM_CAMPAIGN);
|
||||
const cjEvent = getQuerystringParameter(queryStrings.CJ_EVENT);
|
||||
// helper check for if an object is defined (but maybe falsey)
|
||||
const isDefined = (x) => x !== null && x !== undefined;
|
||||
if (isDefined(cjEvent) != "") {
|
||||
const cjeCookieName = cookieNames.CJE;
|
||||
if (!isCookieSet(cjeCookieName)) {
|
||||
createCJEventCookie(cjEvent, cjeCookieName);
|
||||
}
|
||||
}
|
||||
//Firstly, Can't continue without utm-source or utm-medium.
|
||||
//Secondly, Ignore the advertiser for CJ-affiliate-click and Email-click.
|
||||
if (
|
||||
!isDefined(utmSource) ||
|
||||
isDefined(utmSource) == "" ||
|
||||
!isDefined(utmMedium) ||
|
||||
isDefined(utmMedium) == "" ||
|
||||
utmSource?.toLowerCase() == queryStrings.CJUNCTION ||
|
||||
utmMedium?.toLowerCase() == queryStrings.EMAIL ||
|
||||
utmMedium?.toLowerCase() == queryStrings.ORGANIC ||
|
||||
utmMedium?.toLowerCase() == queryStrings.ORGANIC_SOCIAL
|
||||
) {
|
||||
return;
|
||||
}
|
||||
//UTC date time format yyyy-MM-dd/HH:mm:ss
|
||||
const currentDateTime = new Date().toISOString().replace(/T/, "/").replace(/\..+/, "");
|
||||
|
||||
//Format cookie, by removing spaces and special characters.
|
||||
utmSource = FormatCookieElementName(utmSource);
|
||||
utmMedium = FormatCookieElementName(utmMedium);
|
||||
utmCampaign = FormatCookieElementName(utmCampaign);
|
||||
|
||||
var cookieNameBuilder = utmSource + "_" + utmMedium;
|
||||
//Since utmCampaign is optional, ignore the rest.
|
||||
if (isDefined(utmCampaign) && utmCampaign != "") {
|
||||
cookieNameBuilder = cookieNameBuilder + "_" + utmCampaign;
|
||||
}
|
||||
const cookieName =
|
||||
(cookieNameBuilder.length > applicationConfig.COOKIE_NAME_LENGTH_MAX_LIMIT
|
||||
? cookieNameBuilder.substring(0, applicationConfig.COOKIE_NAME_LENGTH_MAX_LIMIT)
|
||||
: cookieNameBuilder) + applicationConfig.AFFILIATE_COOKIE_CONTAINING_NAME;
|
||||
|
||||
if (!isCookieSet(cookieName)) {
|
||||
const values = [
|
||||
`utm_source= ${utmSource}`,
|
||||
`utm_medium= ${utmMedium}`,
|
||||
`utm_campaign= ${utmCampaign}`,
|
||||
`timestamp= ${currentDateTime}`,
|
||||
`tagEvent= ${cjEvent}`,
|
||||
];
|
||||
let valueString = values.join("&");
|
||||
createOrUpdateCookie(cookieName, valueString, {
|
||||
useDefaultFunnelCookieAttributes: true,
|
||||
maxAge: cookieExpirations.NON_CJ,
|
||||
});
|
||||
} else {
|
||||
const cookieValue = getCookieValueByName(cookieName);
|
||||
if (cookieValue) {
|
||||
let cookieValueObj = convertStringToObject(cookieValue);
|
||||
cookieValueObj.timestamp = currentDateTime; // Update the property
|
||||
// Set the updated cookie
|
||||
const cookieValueString = objectToString(cookieValueObj);
|
||||
createOrUpdateCookie(cookieName, cookieValueString, {
|
||||
useDefaultFunnelCookieAttributes: true,
|
||||
maxAge: cookieExpirations.NON_CJ,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===========================
|
||||
= PRIVATE FUNCTIONS =
|
||||
|
|
@ -253,7 +328,7 @@ function setFunnelCookieProperties(properties) {
|
|||
function createOrUpdateCookie(
|
||||
key,
|
||||
value = "",
|
||||
{ useDefaultFunnelCookieAttributes = true, maxAge, isSecure = true }
|
||||
{ useDefaultFunnelCookieAttributes = true, maxAge, isSecure = true, crossSiteAccess = false }
|
||||
) {
|
||||
let cookieToAdd = `${key}=${value}; `;
|
||||
|
||||
|
|
@ -266,6 +341,9 @@ function createOrUpdateCookie(
|
|||
if (!isNaN(maxAge)) {
|
||||
cookieToAdd += `max-age=${maxAge};`;
|
||||
}
|
||||
if (crossSiteAccess && isSecure) {
|
||||
cookieToAdd += `sameSite=None;`;
|
||||
}
|
||||
|
||||
document.cookie = cookieToAdd;
|
||||
}
|
||||
|
|
@ -315,3 +393,42 @@ function getCookiesContainingName(name) {
|
|||
}
|
||||
return matchingCookies;
|
||||
}
|
||||
function createCJEventCookie(cjEvent, cookieName) {
|
||||
createOrUpdateCookie(cookieName, cjEvent, {
|
||||
useDefaultFunnelCookieAttributes: true,
|
||||
maxAge: cookieExpirations.CJE,
|
||||
isSecure: true,
|
||||
crossSiteAccess: true,
|
||||
});
|
||||
}
|
||||
|
||||
function FormatCookieElementName(cookie) {
|
||||
// Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
|
||||
const problemSymbols = '\\s\\(\\)<>@,;:\\\\/\\[\\]\\?=\\{}"';
|
||||
const otherSymbols = "!#$%^&+\\-*|~`";
|
||||
const symbolsToIgnore = new RegExp("[" + problemSymbols + otherSymbols + "]+", "g");
|
||||
|
||||
return (cookie || "").replace(symbolsToIgnore, ".");
|
||||
}
|
||||
|
||||
function convertStringToObject(str) {
|
||||
let obj = {};
|
||||
let pairs = str.split("&");
|
||||
|
||||
pairs.forEach((pair) => {
|
||||
let [key, value] = pair.split("=");
|
||||
obj[key] = value;
|
||||
});
|
||||
|
||||
return obj;
|
||||
}
|
||||
function objectToString(obj) {
|
||||
let str = "";
|
||||
for (let key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
str += key + "=" + obj[key] + "&";
|
||||
}
|
||||
}
|
||||
// Remove the trailing '&'
|
||||
return str.slice(0, -1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {
|
|||
updateSessionIdCookie,
|
||||
deleteFunnelCookie,
|
||||
getAffiliateCookies,
|
||||
setupAdvertiserTracking,
|
||||
} from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { loadSessionIfPresent, saveSession } from "@/helpers/heritage-integration/order-helper";
|
||||
import {
|
||||
|
|
@ -103,7 +104,7 @@ const routes = [
|
|||
if (affiliateCookies != null && affiliateCookies.length > 0) {
|
||||
store.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies);
|
||||
}
|
||||
|
||||
setupAdvertiserTracking();
|
||||
const loadSessionResponse = await loadSessionIfPresent(
|
||||
to.query.isInsurance != null
|
||||
? to.query.isInsurance == "true"
|
||||
|
|
|
|||
Loading…
Reference in a new issue