Skip to content

feat: [EXA-1487] node-view event tracking#282

Draft
Samuel Durkin (FailedSitcom) wants to merge 14 commits into
mainfrom
EXA-1487-extend-sdk-to-send-ex-o-enriched-events
Draft

feat: [EXA-1487] node-view event tracking#282
Samuel Durkin (FailedSitcom) wants to merge 14 commits into
mainfrom
EXA-1487-extend-sdk-to-send-ex-o-enriched-events

Conversation

@FailedSitcom
Copy link
Copy Markdown

@FailedSitcom Samuel Durkin (FailedSitcom) commented May 22, 2026

  • Added initial tracking if node-view events for validation of proposed structure
  • Added autoTrackNodeInteraction prop to allow users to control tracking of node views (and eventually clicks/hovers)

Add SourceMap, SourceMapLayer, SourceMapNode and SourceMapVariant schemas
representing the XDA extensions.sourceMap structure.

Add NodeViewEvent (type: 'exo_view') extending UniversalEventProperties
with required node fields (entityId, entityKind, variant, optimizationId,
viewId, viewDurationMs) and optional brief fields (entityKindId, entryIds,
layers, parameters, parentExperienceId).

Introduce ExoNodeLayer as the resolved layer shape for exo_* events
(entityKind, entityId, variant?, optimizationId?) — distinct from the
raw SourceMapLayer which carries unresolved indices.

Register NodeViewEvent in the InsightsEvent discriminated union.
Add NodeViewBuilderArgs Zod schema extending UniversalEventBuilderArgs
with the required exo_view fields and the optional brief fields
(entityKindId, entryIds, layers, parameters, parentExperienceId).

Add EventBuilder.buildNodeView() which assembles the exo_view payload
via buildUniversalEventProperties.

Add CoreStatefulEventEmitter.trackNodeView() routing to sendInsightsEvent,
with a trackNodeView -> 'exo_view' entry in CONSENT_EVENT_TYPE_MAP.
Add NODE_VIEW_SELECTOR ('[data-ctfl-node-id]') constant.

Add resolveNodeViewPayload() which resolves entityId, entityKind,
optimizationId and variant from an XDA extensions.sourceMap for a
given rendered node ID, walking the node's own layer chain from the
scope position upward.

Add createNodeViewDetector() backed by ElementViewObserver that reads
data-ctfl-* dataset attributes and calls core.trackNodeView().

Add NodeViewRuntime which uses ElementExistenceObserver to auto-discover
[data-ctfl-node-id] elements and delegates to createNodeViewDetector.

Wire NodeViewRuntime into ContentfulOptimization: start/stop on consent
change, stop on reset, destroy on destroy.

Extend CtflDataset with ctflNodeId, ctflEntityId, ctflEntityKind and
ctflVariant. Re-export resolveNodeViewPayload from the package index.
The brief marks anonymousId as a required event field. Add it to the
NodeViewEvent schema as a required string ahead of the type discriminator.
…ackNodeView

Introduce NodeViewTrackingArgs as the public-facing type for runtime
callers — it extends NodeViewBuilderArgs but makes anonymousId optional.

trackNodeView() now accepts NodeViewTrackingArgs and derives anonymousId
from the active profile signal when the caller omits it, falling back to
an empty string. buildNodeView() threads anonymousId onto the event payload.
Introduces `autoTrackNodeInteraction` config option (consistent with
`autoTrackEntryInteraction` naming) with a deprecated `autoTrackNodeViews`
alias. Centralises consent + node view start/stop into `reconcileAutoTracking`.
Adds per-element opt-out via `data-ctfl-track-node-views="false"` dataset
attribute and exports `NODE_VIEW_SELECTOR` from the package index.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Expands ResolvedNodeMetadata to include all optional exo_view fields
(entityKindId, entryIds, layers, parentExperienceId). resolveNodeViewPayload
now builds the full ExoNodeLayer chain and walks ancestors to find the
parent Experience. createNodeViewDetector reads the new dataset attributes
(ctflEntityKindId, ctflEntryIds as CSV, ctflLayers as JSON,
ctflParentExperienceId) and passes them through to trackNodeView.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Expands the ref callback to serialize entityKindId, entryIds (as CSV),
layers (as JSON), and parentExperienceId onto the element dataset so all
optional exo_view fields are available to NodeViewRuntime. Clears the
new attributes when payload is undefined.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…deInteraction

The deprecated alias was never shipped to main, so there is nothing to
migrate. Removes the field from the config interface and collapses the
two-arg resolveAutoTrackNodeInteractionOptions back to a single arg.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@FailedSitcom Samuel Durkin (FailedSitcom) force-pushed the EXA-1487-extend-sdk-to-send-ex-o-enriched-events branch from 861b021 to 7b4208a Compare May 22, 2026 13:32
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