-
Notifications
You must be signed in to change notification settings - Fork 480
feat(analytics): Implement queue persistence for traditional page navigations #34367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(analytics): Implement queue persistence for traditional page navigations #34367
Conversation
72e3bf2 to
eef7488
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Implements sessionStorage-backed event queue persistence in the Analytics SDK to survive traditional (full page) navigations, and adds dynamic SDK configuration sourced from the Content Analytics App secrets and injected into the analytics script tag.
Changes:
- Backend: load analytics configuration from app secrets and inject new script
data-*attributes viaanalytics_head.html. - Frontend SDK: persist/restore queued events via sessionStorage and add parsing/sanitization for
data-analytics-config. - Tests/models/constants: add persistence model/constants and expand unit test coverage for persistence + config parsing.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| dotCMS/src/main/resources/ca/html/analytics_head.html | Adds new data-* attributes for impressions/clicks/advanced config injection. |
| dotCMS/src/main/resources/apps/dotContentAnalytics-config.yml | Adds new admin-configurable secrets for analytics toggles and advanced JSON config. |
| dotCMS/src/main/java/com/dotcms/rest/api/v1/analytics/content/util/ContentAnalyticsUtil.java | Adds helper to fetch all app secrets for a site. |
| dotCMS/src/main/java/com/dotcms/analytics/web/AnalyticsWebAPIImpl.java | Replaces hardcoded placeholder values with app secret values when generating the injected script. |
| core-web/libs/sdk/analytics/src/lib/core/shared/utils/dot-analytics.utils.ts | Adds data-analytics-config parsing/sanitization and safe sessionStorage remove helper. |
| core-web/libs/sdk/analytics/src/lib/core/shared/utils/dot-analytics.utils.spec.ts | Adds unit tests for advanced config parsing and attribute toggles. |
| core-web/libs/sdk/analytics/src/lib/core/shared/queue/dot-analytics.queue.utils.ts | Implements sessionStorage persistence for queued events across reloads and tab ID support. |
| core-web/libs/sdk/analytics/src/lib/core/shared/queue/dot-analytics.queue.utils.spec.ts | Adds unit tests for persistence lifecycle, corrupted storage, quota errors, etc. |
| core-web/libs/sdk/analytics/src/lib/core/shared/models/event.model.ts | Adds PersistedQueue interface for sessionStorage representation. |
| core-web/libs/sdk/analytics/src/lib/core/shared/constants/dot-analytics.constants.ts | Adds persistence constants (storage keys, version, max age). |
core-web/libs/sdk/analytics/src/lib/core/shared/queue/dot-analytics.queue.utils.ts
Show resolved
Hide resolved
core-web/libs/sdk/analytics/src/lib/core/shared/queue/dot-analytics.queue.utils.spec.ts
Show resolved
Hide resolved
core-web/libs/sdk/analytics/src/lib/core/shared/utils/dot-analytics.utils.ts
Show resolved
Hide resolved
core-web/libs/sdk/analytics/src/lib/core/shared/queue/dot-analytics.queue.utils.ts
Outdated
Show resolved
Hide resolved
dotCMS/src/main/java/com/dotcms/analytics/web/AnalyticsWebAPIImpl.java
Outdated
Show resolved
Hide resolved
core-web/libs/sdk/analytics/src/lib/core/shared/utils/dot-analytics.utils.ts
Outdated
Show resolved
Hide resolved
core-web/libs/sdk/analytics/src/lib/core/shared/queue/dot-analytics.queue.utils.ts
Show resolved
Hide resolved
core-web/libs/sdk/analytics/src/lib/core/shared/queue/dot-analytics.queue.utils.ts
Show resolved
Hide resolved
core-web/libs/sdk/analytics/src/lib/core/shared/queue/dot-analytics.queue.utils.ts
Outdated
Show resolved
Hide resolved
d99d1ac to
19417eb
Compare
…age and dynamically load analytics configuration from app secrets.
… analytics queue - Introduced constants for queue persistence configuration, including session storage keys and event age limits. - Implemented a interface to structure the data stored in sessionStorage. - Updated to manage tab IDs and persist events across page navigations. - Added tests for queue persistence, ensuring events are correctly stored, retrieved, and validated. - Enhanced error handling for sessionStorage operations, including quota management and corrupted data scenarios.
… JSON parsing - Rename snake_case params to camelCase in dotContentAnalytics-config.yml (auto_page_view → autoPageView, content_impression → contentImpression, etc.) - Update placeholder references in AnalyticsWebAPIImpl.java and analytics_head.html - Add XSS escaping for user-provided values (siteAuth, advancedConfig) - Improve VTL-style single-quoted JSON parsing with targeted quote replacement - Refactor config resolution to use explicit priority order: defaults → JSON config → attributes - Add server and siteAuth validation in sanitizeAdvancedConfig - Add unit tests for new utility functions - Update queue utils and related specs
…ored tests will be fixed in a separate ticket.
…gurations, including UI rendering, styling, and backend validation adjustments
1f40f5b to
8db94a5
Compare
Summary
This PR implements event persistence using sessionStorage for the Analytics SDK, enabling reliable event tracking across traditional page navigations where the SDK reloads on each page. Additionally, it
introduces dynamic configuration loading from the Content Analytics App secrets, allowing fine-grained control over SDK behavior through the dotCMS admin UI.
Related Issue: #34357
Apps Changes
CleanShot.2026-01-28.at.11.58.53.mp4
Changes Made
Backend
Dynamic Configuration Loading (
AnalyticsWebAPIImpl.java:129-147):content_impression,content_click,advanced_configContentAnalyticsUtil.getAppSecrets()Content Analytics App Configuration (
dotContentAnalytics-config.yml):auto_page_viewtoggle (default: true) - control automatic pageview trackingcontent_impressiontoggle (default: false) - enable contentlet impression trackingcontent_clicktoggle (default: false) - enable contentlet click trackingdebugtoggle (default: false) - enable browser console debug loggingadvanced_configJSON field for fine-tuned SDK configuration (queue batching, impression thresholds, etc.)HTML Template (
analytics_head.html):data-analytics-impressions,data-analytics-clicks,data-analytics-configFrontend (Analytics SDK)
Queue Persistence (
dot-analytics.queue.utils.ts:43-255):PersistedQueuemodel for sessionStorage structure with versioningTAB_ID_STORAGE_KEY)beforeunloadevent)eventsForPersistence) synchronized with smartQueueConfiguration Parsing (
dot-analytics.utils.ts:292-330):data-analytics-configJSON attribute parsing from script tagsanitizeAdvancedConfig()to validate and sanitize JSON configurationUtility Enhancements (
dot-analytics.utils.ts):safeSessionStorage.removeItem()for storage cleanupcreateContentletObserver()to handle<head>script placement edge caseConstants (
dot-analytics.constants.ts:219-247):TAB_ID_STORAGE_KEY- persistent tab identifier across navigationsQUEUE_STORAGE_KEY_PREFIX- sessionStorage key prefix for queuesQUEUE_STORAGE_VERSION- versioning for backward compatibilityMAX_EVENT_AGE_MS- 24-hour event expiration thresholdModels (
event.model.ts:218-231):PersistedQueueinterface with version, tabId, timestamp, and events arrayTests
Queue Persistence Tests (
dot-analytics.queue.utils.spec.ts):Utility Tests (
dot-analytics.utils.spec.ts):Technical Details
Event Persistence Architecture
The solution addresses the challenge of traditional page navigations where the JavaScript SDK is destroyed and reloaded on each page. The architecture works as follows:
Tab Identification: Each browser tab gets a unique ID stored in sessionStorage (
dot_analytics_tab_id) that persists across page navigations.Event Queuing: Events are buffered in memory and simultaneously tracked in a parallel array for persistence.
Pre-Navigation Persistence: On
beforeunloadevent, pending events are written to sessionStorage underdot_analytics_queue_{tabId}.Post-Navigation Recovery: On next page load, SDK checks for persisted queue, validates structure/age, and automatically adds events back to the queue for sending.
Cleanup: After successful transmission, persisted queue is removed from sessionStorage to avoid duplication.
Configuration Flow
analytics_head.html) injects configuration as data attributesThis eliminates hardcoded defaults and enables per-site customization without code changes.
Breaking Changes
None. All new configuration parameters have backward-compatible defaults:
auto_page_view: defaults totrue(existing behavior)content_impression: defaults tofalse(opt-in)content_click: defaults tofalse(opt-in)advanced_config: optional, SDK uses defaults if not providedExisting installations continue working without configuration changes.
Testing
Test Coverage Highlights
Related Issues
Closes #34357
Additional Notes
Traditional Rendering Limitations
Traditional dotCMS pages require
data-dot-*attributes on HTML elements for content impression/click tracking. The current tests only validate pageview events for traditional rendering, with contentimpression tests skipped until rendering implementation is complete.
sessionStorage Quota
The implementation includes quota exceeded handling - if sessionStorage is full, the SDK continues operating normally but events won't persist across navigations. This is logged as a warning for debugging
purposes.
Event Expiration
Persisted events older than 24 hours are automatically discarded on next page load to prevent stale event accumulation and ensure data freshness.
This PR fixes: #34357