Skip to content

Conversation

@oidacra
Copy link
Member

@oidacra oidacra commented Jan 21, 2026

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):

    • Refactored to read analytics configuration from App secrets instead of hardcoded values
    • Added support for new configuration parameters: content_impression, content_click, advanced_config
    • Configuration now dynamically populated from ContentAnalyticsUtil.getAppSecrets()
  • Content Analytics App Configuration (dotContentAnalytics-config.yml):

    • Added auto_page_view toggle (default: true) - control automatic pageview tracking
    • Added content_impression toggle (default: false) - enable contentlet impression tracking
    • Added content_click toggle (default: false) - enable contentlet click tracking
    • Added debug toggle (default: false) - enable browser console debug logging
    • Added advanced_config JSON field for fine-tuned SDK configuration (queue batching, impression thresholds, etc.)
    • Enhanced parameter descriptions with usage examples
  • HTML Template (analytics_head.html):

    • Updated script tag to include new data attributes: data-analytics-impressions, data-analytics-clicks, data-analytics-config
    • Multi-line formatting for improved readability

Frontend (Analytics SDK)

  • Queue Persistence (dot-analytics.queue.utils.ts:43-255):

    • Implemented PersistedQueue model for sessionStorage structure with versioning
    • Added unique tab ID generation and storage (TAB_ID_STORAGE_KEY)
    • Queue lifecycle management:
      • Load persisted events on SDK initialization
      • Persist events to sessionStorage before page unload (beforeunload event)
      • Clear storage after successful event transmission
      • Validate and discard events older than 24 hours
    • Parallel event tracking array (eventsForPersistence) synchronized with smartQueue
    • Handles sessionStorage quota exceeded gracefully
  • Configuration Parsing (dot-analytics.utils.ts:292-330):

    • Added data-analytics-config JSON attribute parsing from script tag
    • Implemented sanitizeAdvancedConfig() to validate and sanitize JSON configuration
    • Prevents pollution from unknown properties with strict type checking
    • Supports both single and double quotes in JSON for VTL compatibility
  • Utility Enhancements (dot-analytics.utils.ts):

    • Added safeSessionStorage.removeItem() for storage cleanup
    • Improved createContentletObserver() to handle <head> script placement edge case
    • Added warning when analytics script wrapper not found
  • Constants (dot-analytics.constants.ts:219-247):

    • TAB_ID_STORAGE_KEY - persistent tab identifier across navigations
    • QUEUE_STORAGE_KEY_PREFIX - sessionStorage key prefix for queues
    • QUEUE_STORAGE_VERSION - versioning for backward compatibility
    • MAX_EVENT_AGE_MS - 24-hour event expiration threshold
  • Models (event.model.ts:218-231):

    • Added PersistedQueue interface with version, tabId, timestamp, and events array

Tests

  • Queue Persistence Tests (dot-analytics.queue.utils.spec.ts):

    • 314 lines of comprehensive test coverage for queue lifecycle
    • Tests for loading, persisting, clearing, and validating events
    • Edge cases: corrupted data, quota exceeded, expired events
    • Navigation scenarios: event flushing before unload
  • Utility Tests (dot-analytics.utils.spec.ts):

    • 204 additional lines of test coverage
    • Advanced config parsing and sanitization validation
    • sessionStorage operation error handling

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:

  1. Tab Identification: Each browser tab gets a unique ID stored in sessionStorage (dot_analytics_tab_id) that persists across page navigations.

  2. Event Queuing: Events are buffered in memory and simultaneously tracked in a parallel array for persistence.

  3. Pre-Navigation Persistence: On beforeunload event, pending events are written to sessionStorage under dot_analytics_queue_{tabId}.

  4. 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.

  5. Cleanup: After successful transmission, persisted queue is removed from sessionStorage to avoid duplication.

Configuration Flow

  1. Admin Configuration: User configures settings in Content Analytics App (dotCMS admin UI)
  2. Secret Storage: Configuration stored as App secrets per site
  3. Template Rendering: VTL template (analytics_head.html) injects configuration as data attributes
  4. SDK Initialization: JavaScript SDK reads attributes from script tag and parses JSON config
  5. Runtime Behavior: SDK behavior dynamically adjusted based on configuration

This 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 to true (existing behavior)
  • content_impression: defaults to false (opt-in)
  • content_click: defaults to false (opt-in)
  • advanced_config: optional, SDK uses defaults if not provided

Existing installations continue working without configuration changes.

Testing

  • Unit tests added for queue persistence lifecycle (314 lines)
  • Unit tests added for configuration parsing and sanitization (204 lines)
  • Integration tests validated with Playwright test suite (36 tests, 33 passing, 3 skipped)
  • Manual testing performed on traditional pages (dotCMS rendering)
  • Manual testing performed on headless Next.js application

Test Coverage Highlights

  • Queue persistence across page navigations
  • SessionStorage validation and error handling
  • Configuration JSON parsing with invalid input scenarios
  • Tab ID generation and persistence
  • Event age validation (24-hour expiration)
  • Quota exceeded graceful degradation

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 content
impression 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

@oidacra oidacra force-pushed the 34357-implement-queue-traditional-pages-analytics branch 2 times, most recently from 72e3bf2 to eef7488 Compare January 23, 2026 19:07
@oidacra oidacra changed the title feat(analytics): Implement analytics event persistence to sessionStor… feat(analytics): Implement queue persistence for traditional page navigations Jan 23, 2026
@oidacra oidacra marked this pull request as ready for review January 23, 2026 19:12
@nicobytes nicobytes requested a review from Copilot January 23, 2026 21:55
Copy link
Contributor

Copilot AI left a 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 via analytics_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).

@oidacra oidacra force-pushed the 34357-implement-queue-traditional-pages-analytics branch 2 times, most recently from d99d1ac to 19417eb Compare January 27, 2026 16:15
oidacra and others added 5 commits January 28, 2026 13:09
…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
@oidacra oidacra force-pushed the 34357-implement-queue-traditional-pages-analytics branch from 1f40f5b to 8db94a5 Compare January 28, 2026 18:09
@oidacra oidacra enabled auto-merge January 28, 2026 20:43
@oidacra oidacra added this pull request to the merge queue Jan 29, 2026
Merged via the queue into main with commit 9d7a8d4 Jan 29, 2026
39 checks passed
@oidacra oidacra deleted the 34357-implement-queue-traditional-pages-analytics branch January 29, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Implement sessionStorage-based queue persistence for traditional web pages in Analytics SDK

4 participants