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
29 changes: 29 additions & 0 deletions src/Rokt-Kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ interface PageEvent {
pageUrl: string;
sourceMessageId: string;
timestamp: number;
pageTitle?: string;
canonicalUrl?: string;
activeTimeOnSite?: number;
// Derived at transmission not at capture based
// on the next page view's activeTimeOnSite,
Expand Down Expand Up @@ -508,6 +510,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 @@ -917,6 +928,16 @@ class RoktKit implements KitInterface {
timestamp: event.Timestamp,
};

const pageTitle = document.title;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Should this come from event since it shoudl be there already in the edge case small chance it's different from document.title?

Suggested change
const pageTitle = document.title;
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 @@ -970,6 +991,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
113 changes: 113 additions & 0 deletions test/src/tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5687,6 +5687,79 @@ describe('Rokt Forwarder', () => {
]);
});

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('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 @@ -5989,6 +6062,46 @@ describe('Rokt Forwarder', () => {
]);
});

it('carries pageTitle and canonicalUrl through selectPlacements when stored', async () => {
window.localStorage.setItem(
'mpPageViews',
JSON.stringify([
{
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