Skip to content

Enhance type 1 video page load tracking with viewport observation#1872

Merged
subodhr258 merged 3 commits into
mainfrom
feat/type-1-tracking-enhancement
May 22, 2026
Merged

Enhance type 1 video page load tracking with viewport observation#1872
subodhr258 merged 3 commits into
mainfrom
feat/type-1-tracking-enhancement

Conversation

@coderGtm
Copy link
Copy Markdown
Contributor

@coderGtm coderGtm commented May 18, 2026

Issue: #1870

What changed

  • type 1 is no longer sent as one bulk request on page load for all videos.
  • It should now fire per video instance, only the first time that instance enters the viewport.

This pull request refactors and improves the video analytics tracking logic in assets/src/js/godam-player/analytics.js. The main focus is to ensure that "page_load" (type 1) analytics events are sent exactly once per video instance, triggered when the video enters the viewport, and to deduplicate these events across different code paths. The code now uses IntersectionObserver for more accurate event timing and centralizes the logic for identifying video instances.

Key improvements include:

Per-Instance Page Load Analytics & Deduplication:

  • Introduced helper functions (resolveAnalyticsVideoElement, getPageLoadVideoInfo, trackPageLoadForVideo, observePageLoadForVideo) to reliably identify video instances and ensure "page_load" events are sent once per instance, either on viewport entry or as a fallback.
  • Updated the documentation and logic in analytics event sending to clarify and enforce the new deduplication behavior for type 1 events, preventing duplicates from multiple triggers. [1] [2]

Event Triggering & Observer Usage:

  • Replaced the previous approach of sending a single "page_load" event for all videos on DOMContentLoaded with per-instance observation: each video now sends its event when it first becomes at least 10% visible in the viewport.
  • On player setup and readiness, each video is registered with the observer to ensure consistent analytics even for dynamically loaded players.

Cleanup & Resource Management:

  • On player disposal, the video instance is unobserved and removed from the observer's tracking set to prevent memory leaks and ensure correct analytics behavior.

Recordings

Gutenberg

https://app.godam.io/web/video/uf8ccm7ph1

Product page

https://app.godam.io/web/video/88qirgv3mb

Elementor

https://app.godam.io/web/video/uf6lufs4j3

WPBakery + Gallery block analytics

https://app.godam.io/web/video/tt4l56nv4d

Test: Type 2 requests with autoplay

Type 2 requests successfully not going when video is set to autoplay. This is because video only starts playing when it is in the viewport.
https://app.godam.io/web/video/6326fdottl

Copilot AI review requested due to automatic review settings May 18, 2026 11:37
@coderGtm coderGtm changed the title Feat/type 1 tracking enhancement Enhance type 1 video page load tracking with viewport observation May 18, 2026
@subodhr258 subodhr258 requested review from elifvish and subodhr258 May 18, 2026 11:40
Copy link
Copy Markdown
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

Refactors GoDAM player analytics so type 1 (“page_load”) events are emitted per video instance when that instance first enters the viewport, while deduplicating type 1 sends across viewport-triggered and heatmap-triggered code paths.

Changes:

  • Added helpers to resolve the canonical analytics video element and to build per-instance tracking metadata.
  • Introduced an IntersectionObserver flow to send type 1 on first viewport entry (with deduplication shared across triggers).
  • Added cleanup on player disposal to unobserve tracked elements and avoid lingering observers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread assets/src/js/godam-player/analytics.js
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 18, 2026

🔍 WordPress Plugin Check Report

❌ Status: Failed

📊 Report

🎯 Total Issues ❌ Errors ⚠️ Warnings
15 1 14

❌ Errors (1)

📁 readme.txt (1 error)
📍 Line 🔖 Check 💬 Message
0 outdated_tested_upto_header Tested up to: 6.9 < 7.0. The "Tested up to" value in your plugin is not set to the current version of WordPress. This means your plugin will not show up in searches, as we require plugins to be compatible and documented as tested up to the most recent version of WordPress.

⚠️ Warnings (14)

📁 readme.txt (2 warnings)
📍 Line 🔖 Check 💬 Message
0 mismatched_plugin_name Plugin name "GoDAM - Organize WordPress Media Library & File Manager with Unlimited Folders for Images, Videos & more" is different from the name declared in plugin header "GoDAM".
0 trademarked_term The plugin name includes a restricted term. Your chosen plugin name - "GoDAM - Organize WordPress Media Library & File Manager with Unlimited Folders for Images, Videos & more" - contains the restricted term "wordpress" which cannot be used at all in your plugin name.
📁 composer.json (1 warning)
📍 Line 🔖 Check 💬 Message
0 missing_composer_json_file The "/vendor" directory using composer exists, but "composer.json" file is missing.
📁 assets/build/css/main.css (1 warning)
📍 Line 🔖 Check 💬 Message
0 EnqueuedStylesScope This style is being loaded in all contexts.
📁 assets/src/libs/analytics.min.js (5 warnings)
📍 Line 🔖 Check 💬 Message
0 EnqueuedScriptsScope This script is being loaded in all frontend contexts.
0 NonBlockingScripts.NoStrategy This script on http://localhost:8880 (with handle analytics-library) is loaded in the footer. Consider a defer or async script loading strategy instead.
0 NonBlockingScripts.NoStrategy This script on http://localhost:8880/2026/05/22/hello-world/ (with handle analytics-library) is loaded in the footer. Consider a defer or async script loading strategy instead.
0 NonBlockingScripts.NoStrategy This script on http://localhost:8880/sample-page/ (with handle analytics-library) is loaded in the footer. Consider a defer or async script loading strategy instead.
0 NonBlockingScripts.NoStrategy This script on http://localhost:8880/demo-attachment-post/ (with handle analytics-library) is loaded in the footer. Consider a defer or async script loading strategy instead.
📁 assets/build/js/main.min.js (5 warnings)
📍 Line 🔖 Check 💬 Message
0 EnqueuedScriptsScope This script is being loaded in all frontend contexts.
0 NonBlockingScripts.NoStrategy This script on http://localhost:8880 (with handle rtgodam-script) is loaded in the footer. Consider a defer or async script loading strategy instead.
0 NonBlockingScripts.NoStrategy This script on http://localhost:8880/2026/05/22/hello-world/ (with handle rtgodam-script) is loaded in the footer. Consider a defer or async script loading strategy instead.
0 NonBlockingScripts.NoStrategy This script on http://localhost:8880/sample-page/ (with handle rtgodam-script) is loaded in the footer. Consider a defer or async script loading strategy instead.
0 NonBlockingScripts.NoStrategy This script on http://localhost:8880/demo-attachment-post/ (with handle rtgodam-script) is loaded in the footer. Consider a defer or async script loading strategy instead.

🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

)

* feat: batch type 1 page_load events and gate observer teardown on success

Address two follow-ups from the pre-merge review of #1872:

1. Batching / debouncing: replace the one-fetch-per-intersection model
   with a debounced queue. Intersection events enqueue [videoId, jobId]
   pairs that flush either after 300ms or when the queue hits 10
   entries, preserving the legacy videoIds: [[id, job], ...] schema.
   Reduces singleton inserts on the ingestion side and protects against
   WAF rate-limit thresholds for surfaces that genuinely render N
   inline players (Reels feed, etc.).

2. Defensive observer gating: only call observer.unobserve when
   trackPageLoadForVideo reports it is done with the element. A
   "retry" return (currently only when window.analytics is unset) now
   leaves the IO entry alive so a subsequent intersection tick can
   retry instead of silently dropping the event.

Also flush pending batches through a synchronous keepalive fetch from
the existing visibilitychange/pagehide handlers so in-flight events
survive page teardown without waiting on the DavidWells async queue.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: Increase batch flush delay

* fix: prevent stranded batches when flushPageLoadQueue bails

Both bail paths in flushPageLoadQueue cleared the debounce timer before
deciding whether to drain, so when a bail returned without sending,
the queue could sit until the next intersection event triggered
another enqueue.

- sync + shouldSkipAnalytics: clear the queue. shouldSkipAnalytics()
  is constant for the page session (isAdminPage / preview query param),
  so these events would never be sendable through the async path either.
  Dropping them avoids unbounded queue growth across bfcache restores.

- async + !window.analytics: reschedule the flush. Bail before the
  splice so we don't need the unshift dance, then schedule a new timer
  so a missing analytics library is retried rather than stranding the
  batch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@subodhr258 subodhr258 merged commit 9e80430 into main May 22, 2026
6 of 7 checks passed
@subodhr258 subodhr258 deleted the feat/type-1-tracking-enhancement branch May 22, 2026 11:21
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.

4 participants