Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/Rokt-Kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,15 @@ function sanitizeUrl(href: string): string {
}
}

function readCanonicalUrl(): string | undefined {
const link = document.querySelector<HTMLLinkElement>('link[rel="canonical"]');
const href = link?.href;
if (!href) {
return undefined;
}
return sanitizeUrl(href);
}

function generateIntegrationName(customIntegrationName?: string): string {
const coreSdkVersion = mp().getVersion();
const kitVersion = process.env.PACKAGE_VERSION;
Expand Down Expand Up @@ -867,6 +876,16 @@ class RoktKit implements KitInterface {
timestamp: event.Timestamp,
};

const pageTitle = event.EventAttributes?.title || document.title;
if (pageTitle) {
pageView.pageTitle = pageTitle;
}

const canonicalUrl = readCanonicalUrl();
if (canonicalUrl) {
pageView.canonicalUrl = canonicalUrl;
}

if (Number.isFinite(event.ActiveTimeOnSite)) {
pageView.activeTimeOnSite = event.ActiveTimeOnSite;
}
Expand Down Expand Up @@ -921,6 +940,14 @@ class RoktKit implements KitInterface {
timestamp: pageView.timestamp,
};

if (pageView.pageTitle !== undefined) {
pageEvent.pageTitle = pageView.pageTitle;
}

if (pageView.canonicalUrl !== undefined) {
pageEvent.canonicalUrl = pageView.canonicalUrl;
}

const activeTimeOnSite = pageView.activeTimeOnSite;
const hasActiveTime = activeTimeOnSite !== undefined && Number.isFinite(activeTimeOnSite);
if (hasActiveTime) {
Expand Down
2 changes: 2 additions & 0 deletions src/pageViewStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export interface PageEvent {
pageUrl: string;
sourceMessageId: string;
timestamp: number;
pageTitle?: string;
canonicalUrl?: string;
activeTimeOnSite?: number;
activeTimeOnPage?: number;
}
Expand Down
151 changes: 151 additions & 0 deletions test/src/tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5686,11 +5686,125 @@ describe('Rokt Forwarder', () => {
pageUrl: window.location.href,
sourceMessageId: 'source-message-id-1',
timestamp: 1712345678000,
pageTitle: 'Home',
activeTimeOnSite: 4200,
},
]);
});

it('captures the page title and canonical URL when present', async () => {
document.title = 'Home Page Title';
const canonical = document.createElement('link');
canonical.setAttribute('rel', 'canonical');
canonical.setAttribute('href', 'https://example.com/canonical?tracking=abc#section');
document.head.appendChild(canonical);

try {
await (window as any).mParticle.forwarder.init(
{
accountId: '123456',
},
reportService.cb,
true,
null,
{},
);

await waitForCondition(() => (window as any).mParticle.Rokt.attachKitCalled);

(window as any).mParticle.forwarder.process({
EventName: 'Home Page',
EventCategory: EventType.Unknown,
EventDataType: MessageType.PageView,
SourceMessageId: 'source-message-id-title',
Timestamp: 1712345678000,
});

expect(readStoredPageViews()).toEqual([
{
pageUrl: window.location.href,
sourceMessageId: 'source-message-id-title',
timestamp: 1712345678000,
pageTitle: 'Home Page Title',
canonicalUrl: 'https://example.com/canonical#section',
},
]);
} finally {
document.title = '';
document.head.removeChild(canonical);
}
});

it('prefers the event title over document.title when both are present', async () => {
document.title = 'Document Title';

try {
await (window as any).mParticle.forwarder.init(
{
accountId: '123456',
},
reportService.cb,
true,
null,
{},
);

await waitForCondition(() => (window as any).mParticle.Rokt.attachKitCalled);

(window as any).mParticle.forwarder.process({
EventName: 'Home Page',
EventCategory: EventType.Unknown,
EventDataType: MessageType.PageView,
SourceMessageId: 'source-message-id-event-title',
Timestamp: 1712345678000,
EventAttributes: {
title: 'Event Title',
},
});

expect(readStoredPageViews()).toEqual([
{
pageUrl: window.location.href,
sourceMessageId: 'source-message-id-event-title',
timestamp: 1712345678000,
pageTitle: 'Event Title',
},
]);
} finally {
document.title = '';
}
});

it('omits pageTitle and canonicalUrl when neither is available', async () => {
await (window as any).mParticle.forwarder.init(
{
accountId: '123456',
},
reportService.cb,
true,
null,
{},
);

await waitForCondition(() => (window as any).mParticle.Rokt.attachKitCalled);

(window as any).mParticle.forwarder.process({
EventName: 'Home Page',
EventCategory: EventType.Unknown,
EventDataType: MessageType.PageView,
SourceMessageId: 'source-message-id-bare',
Timestamp: 1712345678000,
});

expect(readStoredPageViews()).toEqual([
{
pageUrl: window.location.href,
sourceMessageId: 'source-message-id-bare',
timestamp: 1712345678000,
},
]);
});

it('omits activeTimeOnSite when the source value is non-finite', async () => {
await (window as any).mParticle.forwarder.init(
{
Expand Down Expand Up @@ -6238,6 +6352,43 @@ describe('Rokt Forwarder', () => {
]);
});

it('carries pageTitle and canonicalUrl through selectPlacements when stored', async () => {
seedStoredPageViews([
{
pageUrl: 'https://example.com/a',
sourceMessageId: 'source-message-id-a',
timestamp: 1712345678000,
pageTitle: 'Page A',
canonicalUrl: 'https://example.com/canonical-a',
},
]);

await (window as any).mParticle.forwarder.init(
{
accountId: '123456',
},
reportService.cb,
true,
null,
{},
);

await waitForCondition(() => (window as any).mParticle.Rokt.attachKitCalled);

await (window as any).mParticle.forwarder.selectPlacements({ attributes: {} });

const forwardedAttributes = (window as any).mParticle.Rokt.selectPlacementsOptions.attributes;
expect(JSON.parse(forwardedAttributes.page_events)).toEqual([
{
pageUrl: 'https://example.com/a',
sourceMessageId: 'source-message-id-a',
timestamp: 1712345678000,
pageTitle: 'Page A',
canonicalUrl: 'https://example.com/canonical-a',
},
]);
});

it('does not add a page_events attribute when no page views are stored', async () => {
await (window as any).mParticle.forwarder.init(
{
Expand Down
Loading