Skip to content
3 changes: 3 additions & 0 deletions libs/blocks/brand-concierge-global/brand-concierge-global.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
openSideModal,
setAuthoredContent,
} from '../brand-concierge/bc-bootstrap.js';
import { initAnalytics } from '../brand-concierge/bc-analytics.js';

let stayActive = false;

Expand Down Expand Up @@ -150,6 +151,8 @@ export default function init(el) {
}
});

initAnalytics();

const rows = el.querySelectorAll(':scope > div');
const [cards, input] = rows;
setAuthoredContent(null, cards, input);
Expand Down
104 changes: 104 additions & 0 deletions libs/blocks/brand-concierge/bc-analytics.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,49 @@
import { getConfig } from '../../utils/utils.js';
import { getChatSessionId } from './bc-utils.js';

export function getAnalyticsLabel(step) {
return `Filters|${getConfig()?.brandConciergeAA ? getConfig()?.brandConciergeAA : 'app-reco'}|bc#${step}`;
}

const recordNavClick = ({ clickType, destinationPage, clickSource } = {}) => {
window.history.replaceState(
{
...window.history.state,
bcClickType: clickType,
bcSourcePage: window.location.href,
bcDestinationPage: destinationPage ?? '',
bcClickSource: clickSource ?? '',
},
'',
);
};

const handleNav = (event) => {
switch (event.eventType) {
case 'card:clicked':
recordNavClick({
clickType: 'product_card_cta',
destinationPage: event.data?.destinationUrl,
});
break;
case 'cta:clicked':
recordNavClick({ clickType: 'cta', clickSource: event.data?.source });
break;
case 'link:clicked':
recordNavClick({
clickType: event.data?.element?.linkType ?? 'inline_hyperlink',
destinationPage: event.data?.element?.href,
});
break;
default:
break;
}
};

/* eslint-disable no-undef, no-underscore-dangle */
export const bcAnalytics = (event) => {
handleNav(event);

if (window?._satellite?.track) {
switch (event.eventType) {
case 'query:submitted':
Expand Down Expand Up @@ -112,8 +150,74 @@ export const bcAnalytics = (event) => {
},
});
break;
case 'navigation:backNavigation': {
const {
clickType = 'unknown',
sessionId = '',
sourcePage = '',
destinationPage = '',
clickSource = '',
loginStatus = '',
navigatedBack = true,
} = event.data ?? {};
const eventName = `BC-chat_${clickType}_back_navigation`;
_satellite.track('event', {
data: {
web: { webInteraction: { name: `${eventName}|loginStatus:${loginStatus}` } },
bc: {
eventName,
timestamp: new Date().toISOString(),
sessionId,
clickType,
sourcePage,
destinationPage,
clickSource,
navigatedBack,
loginStatus,
},
_adobe_corpnew: { digitalData: { primaryEvent: { eventInfo: { interaction: { click: `${eventName}|session:${sessionId}|from:${sourcePage}|to:${destinationPage}|source:${clickSource}|nav:${navigatedBack}|loginStatus:${loginStatus}` } } } } },
},
});
break;
}
default:
break;
}
}
};

const initBackNavAnalytics = () => {
const emitAnalyticsIfBackNav = () => {
const state = window.history.state ?? {};
if (!state.bcClickType) {
return;
}

bcAnalytics({
eventType: 'navigation:backNavigation',
data: {
clickType: state.bcClickType,
sessionId: getChatSessionId(),
sourcePage: state.bcSourcePage ?? window.location.href,
destinationPage: state.bcDestinationPage ?? '',
clickSource: state.bcClickSource ?? '',
loginStatus: window.adobeIMS?.isSignedInUser() ? 'logged-in' : 'logged-out',
navigatedBack: true,
},
});
};

// bfcache restore: page is brought back from memory, init does not re-run.
window.addEventListener('pageshow', (e) => {
if (e.persisted) emitAnalyticsIfBackNav();
});

// full-page back/forward load: init re-runs, navigation type is back_forward.
if (window.performance.getEntriesByType('navigation')[0]?.type === 'back_forward') {
emitAnalyticsIfBackNav();
}
};

export const initAnalytics = () => {
initBackNavAnalytics();
};
14 changes: 12 additions & 2 deletions libs/blocks/brand-concierge/bc-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,28 @@ const getTargetHeight = (target) => {
return target.scrollHeight + (parseFloat(marginBottom) * 2);
};

const BC_SESSION_COOKIE = 'kndctr_9E1005A551ED61CA0A490D45_AdobeOrg_bc_session_id';

export function hasChatCookie() {
const cookies = document.cookie.split(';');
const cookieName = 'kndctr_9E1005A551ED61CA0A490D45_AdobeOrg_bc_session_id';
for (let i = 0; i < cookies.length; i += 1) {
const cookie = cookies[i].trim();
if (cookie.includes(cookieName)) {
if (cookie.includes(BC_SESSION_COOKIE)) {
return true;
}
}
return false;
}

/** Get session ID used to correlate analytics events */
export function getChatSessionId() {
const match = document.cookie
.split(';')
.map((cookie) => cookie.trim())
.find((cookie) => cookie.startsWith(`${BC_SESSION_COOKIE}=`));
return match ? decodeURIComponent(match.slice(BC_SESSION_COOKIE.length + 1)) : '';
}

export function setCssGnavHeight() {
const gnav = document.querySelector('header.global-navigation');
const localGnav = document.querySelector('div.feds-localnav');
Expand Down
3 changes: 3 additions & 0 deletions libs/blocks/brand-concierge/brand-concierge.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createTag } from '../../utils/utils.js';
import { initAnalytics } from './bc-analytics.js';
import {
decorateBackground,
decorateMarqueeBackground,
Expand Down Expand Up @@ -86,6 +87,8 @@ export default async function init(el) {
}
});

initAnalytics();

setCssGnavHeight();

const rows = el.querySelectorAll(':scope > div');
Expand Down
104 changes: 104 additions & 0 deletions libs/c2/blocks/brand-concierge/bc-analytics.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,49 @@
import { getConfig } from '../../../utils/utils.js';
import { getChatSessionId } from './bc-utils.js';

export function getAnalyticsLabel(step) {
return `Filters|${getConfig()?.brandConciergeAA ? getConfig()?.brandConciergeAA : 'app-reco'}|bc#${step}`;
}

const recordNavClick = ({ clickType, destinationPage, clickSource } = {}) => {
window.history.replaceState(
{
...window.history.state,
bcClickType: clickType,
bcSourcePage: window.location.href,
bcDestinationPage: destinationPage ?? '',
bcClickSource: clickSource ?? '',
},
'',
);
};

const handleNav = (event) => {
switch (event.eventType) {
case 'card:clicked':
recordNavClick({
clickType: 'product_card_cta',
destinationPage: event.data?.destinationUrl,
});
break;
case 'cta:clicked':
recordNavClick({ clickType: 'cta', clickSource: event.data?.source });
break;
case 'link:clicked':
recordNavClick({
clickType: event.data?.element?.linkType ?? 'inline_hyperlink',
destinationPage: event.data?.element?.href,
});
break;
default:
break;
}
};

/* eslint-disable no-undef, no-underscore-dangle */
export const bcAnalytics = (event) => {
handleNav(event);

if (window?._satellite?.track) {
switch (event.eventType) {
case 'query:submitted':
Expand Down Expand Up @@ -112,8 +150,74 @@ export const bcAnalytics = (event) => {
},
});
break;
case 'navigation:backNavigation': {
const {
clickType = 'unknown',
sessionId = '',
sourcePage = '',
destinationPage = '',
clickSource = '',
loginStatus = '',
navigatedBack = true,
} = event.data ?? {};
const eventName = `BC-chat_${clickType}_back_navigation`;
_satellite.track('event', {
data: {
web: { webInteraction: { name: `${eventName}|loginStatus:${loginStatus}` } },
bc: {
eventName,
timestamp: new Date().toISOString(),
sessionId,
clickType,
sourcePage,
destinationPage,
clickSource,
navigatedBack,
loginStatus,
},
_adobe_corpnew: { digitalData: { primaryEvent: { eventInfo: { interaction: { click: `${eventName}|session:${sessionId}|from:${sourcePage}|to:${destinationPage}|source:${clickSource}|nav:${navigatedBack}|loginStatus:${loginStatus}` } } } } },
},
});
break;
}
default:
break;
}
}
};

const initBackNavAnalytics = () => {
const emitAnalyticsIfBackNav = () => {
const state = window.history.state ?? {};
if (!state.bcClickType) {
return;
}

bcAnalytics({
eventType: 'navigation:backNavigation',
data: {
clickType: state.bcClickType,
sessionId: getChatSessionId(),
sourcePage: state.bcSourcePage ?? window.location.href,
destinationPage: state.bcDestinationPage ?? '',
clickSource: state.bcClickSource ?? '',
loginStatus: window.adobeIMS?.isSignedInUser() ? 'logged-in' : 'logged-out',
navigatedBack: true,
},
});
};

// bfcache restore: page is brought back from memory, init does not re-run.
window.addEventListener('pageshow', (e) => {
if (e.persisted) emitAnalyticsIfBackNav();
});

// full-page back/forward load: init re-runs, navigation type is back_forward.
if (window.performance.getEntriesByType('navigation')[0]?.type === 'back_forward') {
emitAnalyticsIfBackNav();
}
};

export const initAnalytics = () => {
initBackNavAnalytics();
};
11 changes: 11 additions & 0 deletions libs/c2/blocks/brand-concierge/bc-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ const getTargetHeight = (target) => {
return target.scrollHeight + (parseFloat(marginBottom) * 2);
};

const BC_SESSION_COOKIE = 'kndctr_9E1005A551ED61CA0A490D45_AdobeOrg_bc_session_id';

/** Get session ID used to correlate analytics events */
export function getChatSessionId() {
const match = document.cookie
.split(';')
.map((cookie) => cookie.trim())
.find((cookie) => cookie.startsWith(`${BC_SESSION_COOKIE}=`));
return match ? decodeURIComponent(match.slice(BC_SESSION_COOKIE.length + 1)) : '';
}

export function handleConsent(el) {
if (!window.adobePrivacy) return;
const cookieGrp = window.adobePrivacy.activeCookieGroups();
Expand Down
3 changes: 3 additions & 0 deletions libs/c2/blocks/brand-concierge/brand-concierge.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createTag } from '../../../utils/utils.js';
import { initAnalytics } from './bc-analytics.js';
import {
decorateBackground,
decorateMarqueeBackground,
Expand Down Expand Up @@ -81,6 +82,8 @@ export default async function init(el) {
}
});

initAnalytics();

const rows = el.querySelectorAll(':scope > div');
const [background, header, cards, input, legal] = rows;

Expand Down
Loading
Loading