Skip to content

feat: capture page views and surface as page_events in selectPlacements - #107

Closed
alexs-mparticle wants to merge 11 commits into
developmentfrom
capture-page-views
Closed

feat: capture page views and surface as page_events in selectPlacements#107
alexs-mparticle wants to merge 11 commits into
developmentfrom
capture-page-views

Conversation

@alexs-mparticle

@alexs-mparticle alexs-mparticle commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

Records page-view events as they are logged, persists them durably to the Rokt local-session-attribute store, and surfaces them as a flat page_events array on the next selectPlacements call as targeting context.

What's included

  • Capture (process): page views (EventDataType === 3) are appended to a persisted mpPageViews list (max 25, oldest evicted), guarded so a malformed event can never throw out of the forwarder. Captures EventName, full pageUrl (window.location.href), SourceMessageId, timestamp, ActiveTimeOnSite, and EventAttributes.
  • Flatten (buildPageEvents): each stored view is flattened into a page_events entry — event_name, page_name (from the title attribute), and eventAttributes exploded into attr_-namespaced keys so they can't clobber base fields. The raw nested mpPageViews store is stripped so only the flat copy is sent.
  • timeOnPage: each entry carries a derived timeOnPage — the active time a page was viewed before the next page view was logged (diff of consecutive activeTimeOnSite). Emitted only when it's a genuine non-negative number; omitted for the still-open last entry, negative diffs, and non-numeric values. Derived at read time — nothing extra persisted.
  • Feeding selectPlacements: relaxed returnLocalSessionAttributes() so the store flows through whenever it's available and populated.

Security note (per Rokt secure-coding policy)

pageUrl (full URL incl. query/fragment) and eventAttributes are stored verbatim and may contain PII; they are persisted to browser storage and sent to Rokt. Full-URL was an explicit product choice; sanitizeUrl() isolates the boundary so query/fragment stripping is a one-line change later. The SDK does not run kit user-attribute filters over page-view EventAttributes. Design doc records this in full.

Testing

  • Navigate through a page with an MPA and then triggermParticle.getInstance()._Store.getLocalSessionAttributes() in the dev console.

Expected result:

[
    {
        "attr_hostname": "www.domain.com",
        "event_name": "PageView",
        "page_name": "Online Store",
        "pageUrl": "https://www.domain.com/",
        "sourceMessageId": "80588459-ea2c-491a-9f41-2acc15b8cfb8",
        "timestamp": 1785526522349,
        "activeTimeOnSite": 328892,
        "timeOnPage": 35935
    },
    {
        "attr_hostname": "www.domain.com",
        "event_name": "PageView",
        "page_name": "Online Store | Some Page",
        "pageUrl": "https://www.domain.com/page_1",
        "sourceMessageId": "88a1ef32-83fd-41a8-03d8-04c4c67c879d",
        "timestamp": 1785526728989,
        "activeTimeOnSite": 364827,
        "timeOnPage": 11964
    },
    {
        "attr_hostname": "www.domain.com",
        "event_name": "PageView",
        "page_name": "Online Store | Next Page",
        "pageUrl": "https://www.domain.com/page_2",
        "sourceMessageId": "3c755531-1785-4b23-bf6c-fee3a93cc38e",
        "timestamp": 1785526922622,
        "activeTimeOnSite": 376791
    }
]

Verify the expected payload when making a select placements call:

{
  "active_time_on_site_ms": "427361",
  "page_events": "[ /* stringified array of events with timeOnPage value */ ]",
  // other placement attributes
}

…ents

Derive a flat page_events array from stored page views at selectPlacements
time. Each view's eventAttributes are exploded into attr_-namespaced keys;
the title attribute is surfaced as page_name and EventName as event_name.
The raw nested mpPageViews store is stripped so only the flattened copy is
sent. Relax returnLocalSessionAttributes to no longer require a placement
mapping. Restore the isKitReady guard in process() and remove debug logging.
Compute a timeOnPage field for each page_events entry at read time in
buildPageEvents as the diff of consecutive activeTimeOnSite values — the
active time a page was viewed before the next page view was logged. Emitted
only when it is a genuine, non-negative number; omitted for the still-open
last entry, negative diffs (clock skew, reset, out-of-order), and
non-numeric activeTimeOnSite. Nothing new is persisted; StoredPageView is
unchanged.
…iews

# Conflicts:
#	dist/Rokt-Kit.common.js
#	dist/Rokt-Kit.common.js.map
#	dist/Rokt-Kit.esm.js.map
#	dist/Rokt-Kit.iife.js
#	dist/Rokt-Kit.iife.js.map
Comment thread src/Rokt-Kit.ts Outdated
Comment thread src/Rokt-Kit.ts Outdated

private buildPageEvents(pageViews: StoredPageView[]): Record<string, unknown>[] {
return pageViews.map((pv, i) => {
const flat: Record<string, unknown> = {};

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We should create an explicit type here for safety and it should include timeOnPage as optional.

Comment thread test/src/tests.spec.ts Outdated
EventName: 'Browse',
EventCategory: EventType.Unknown,
EventDataType: MessageType.PageView,
EventDataType: MessageType.PageEvent,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We shouldn't be changing these.

Add an explicit PageEvent return type for buildPageEvents (with timeOnPage
optional) instead of Record<string, unknown>[]. Revert the legacy
#processEvent attribute-mapping tests back to MessageType.PageView and strip
the captured mpPageViews list from their exact-shape assertions via a helper,
since processing a PageView now legitimately captures a page-view record.
@alexs-mparticle
alexs-mparticle deleted the capture-page-views branch July 31, 2026 20:24
@alexs-mparticle

Copy link
Copy Markdown
Collaborator Author

Superseded by #109 — branch renamed to feat/capture-page-views to match our naming convention (the rename closed this PR).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant