Skip to content

feat: Reel Pop analytics — SDK page_load_session_id + Dashboard table#1890

Open
subodhr258 wants to merge 8 commits into
developfrom
feat/reel-pops-analytics
Open

feat: Reel Pop analytics — SDK page_load_session_id + Dashboard table#1890
subodhr258 wants to merge 8 commits into
developfrom
feat/reel-pops-analytics

Conversation

@subodhr258
Copy link
Copy Markdown
Collaborator

@subodhr258 subodhr258 commented May 25, 2026

Summary

Plugin-side counterpart to the already-merged godam-analytics PR #140. Adds a per-page-load UUID v4 (page_load_session_id) to every type=1/2/3 analytics envelope so the microservice can dedup engagement counters with uniqExact(page_load_session_id), keeping derived rates (Engagement / Impressions etc.) bounded ≤ 100%. Exposes godam SDK helpers on window.RTGodamAnalyticsHelpers so godam-for-woo can emit identical normalized UA strings + share the per-page-load session ID for its type=4 (Reel Pop) events. Adds a new "Reel Pops" cumulative table to the GoDAM Dashboard backed by a server-side REST proxy that injects X-API-Key so the browser never sees the key.

SDK changes (assets/src/js/godam-player/)

  • analytics-helpers.js: new getPageLoadSessionId() (UUID v4 with crypto.randomUUID + hand-rolled fallback for mobile Safari < 15.4); added to buildAnalyticsRequestBody envelope.
  • analytics-helpers.js: buildAnalyticsRequestBody now accepts optional reelPopId and only writes reel_pop_id to the body when > 0 — non-Reel-Pop events stay at the same wire shape.
  • analytics.js: trackVideoEvent accepts optional reelPopId and propagates it onto both the auto type=1 page_load payload and the type=2 video_heatmap payload.
  • analytics.js: sendPlayerHeatmap (the unload-flush keepalive path) reads data-reel-pop-id off the <video> element and forwards it on type=2 events. The SDK itself doesn't know what a Reel Pop is — this just opaquely propagates the attribute.
  • analytics.js: exposes window.RTGodamAnalyticsHelpers = { getPageLoadSessionId, getUserAgent } so godam-for-woo (and future plugins) can call them without polluting window.analytics (which is the Analytics library instance).
  • video-analytics-plugin.js: forwards reel_pop_id from track() properties into buildAnalyticsRequestBody.

Dashboard changes

  • New inc/classes/rest-api/class-dashboard.php: GET /godam/v1/dashboard/reel-pops-summary — proxies the microservice /reel-pops/summary endpoint with X-API-Key injected server-side, enriches each row with the WP post title / thumbnail / edit URL, drops rows whose post no longer exists or isn't published, caches the upstream response for 60 s.
  • Registered the new class in inc/classes/class-plugin.php::load_rest_api().
  • New pages/dashboard/components/ReelPopsTable.jsx: single apiFetch on mount; renders one row per Reel Pop with Impressions / Engagement / Closure / Conversion counters; thumbnail + title click-through to the editor; matches the existing top-videos table styling and pagination pattern.
  • Mounted <ReelPopsTable /> in Dashboard.js below the existing top-videos table.

Companion PRs

Test plan

  • npm run build:prod completes without errors.
  • Verified page_load_session_id, RTGodamAnalyticsHelpers, reel_pop_id strings appear in the minified godam-player-analytics.min.js bundle.
  • Verified reel-pops-summary + reel_pop_id strings appear in the minified dashboard.min.js bundle.
  • Manual on test site subodh-multisite.rt.gw:
    • Confirm every video analytics POST body contains page_load_session_id (DevTools Network → request payload).
    • Confirm window.RTGodamAnalyticsHelpers.getPageLoadSessionId() returns the same UUID across multiple calls on one page load.
    • GoDAM Dashboard → confirm Reel Pops table renders (empty state if no Reel Pops yet, otherwise rows with counters + thumbnails).
    • Click a row → lands on the Reel Pop editor.
    • Confirm dashboard table data updates after the next APScheduler tick on the microservice.

🤖 Generated with Claude Code

subodhr258 and others added 8 commits May 25, 2026 11:50
…elope

Co-Authored-By: Claude <noreply@anthropic.com>
…1/2 attribution

Co-Authored-By: Claude <noreply@anthropic.com>
…sent

Co-Authored-By: Claude <noreply@anthropic.com>
….RTGodamAnalyticsHelpers for cross-plugin reuse

Co-Authored-By: Claude <noreply@anthropic.com>
Proxies the godam-analytics /reel-pops/summary endpoint, injecting the API
key + account token server-side and enriching each row with the WP post
title / thumbnail / edit URL for the dashboard table.

Co-Authored-By: Claude <noreply@anthropic.com>
Single apiFetch on mount renders one row per Reel Pop with four cumulative
counters (Impressions / Engagement / Closure / Conversion). Thumbnail +
title click-through to the editor; matches existing top-videos pagination
and styling.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 25, 2026 06:29
Copy link
Copy Markdown
Contributor

@rtBot rtBot left a comment

Choose a reason for hiding this comment

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

Code analysis identified issues

action-phpcs-code-review has identified potential problems in this pull request during automated scanning. We recommend reviewing the issues noted and that they are resolved.

phpcs scanning turned up:

🚫 1 error


Powered by rtCamp's GitHub Actions Library

$url,
array(
'headers' => array( 'X-API-Key' => $api_key ),
'timeout' => 5,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚫 Error: Detected high remote request timeout. timeout is set to 5 (WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout).

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

Adds Reel Pop analytics support end-to-end: a per-page-load UUID (page_load_session_id) included in player analytics envelopes for deduping, exposes SDK helper functions for other plugins, and introduces a new Dashboard “Reel Pops” summary table backed by a server-side REST proxy that injects the API key.

Changes:

  • Player analytics: generate/reuse page_load_session_id, optionally include reel_pop_id, and propagate Reel Pop attribution through the tracking paths.
  • SDK interop: expose window.RTGodamAnalyticsHelpers with getPageLoadSessionId() and getUserAgent().
  • Dashboard: add a REST proxy endpoint for /dashboard/reel-pops-summary and a new React table component rendering cumulative Reel Pop counters.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pages/dashboard/Dashboard.js Mounts the new Reel Pops table in the Dashboard UI.
pages/dashboard/components/ReelPopsTable.jsx Fetches and renders the Reel Pops summary table with pagination/error/loading states.
inc/classes/rest-api/class-dashboard.php Adds REST proxy endpoint to fetch/caches Reel Pops summary and enriches rows with WP metadata.
inc/classes/class-plugin.php Registers the new Dashboard REST controller.
assets/src/js/godam-player/video-analytics-plugin.js Forwards reel_pop_id from track properties into request-body builder.
assets/src/js/godam-player/analytics.js Adds optional reelPopId propagation and exposes helper functions on window.
assets/src/js/godam-player/analytics-helpers.js Implements getPageLoadSessionId() and adds page_load_session_id / optional reel_pop_id to the analytics envelope.

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

Comment on lines +25 to +33
if ( window.crypto?.randomUUID ) {
_pageLoadSessionId = window.crypto.randomUUID();
return _pageLoadSessionId;
}
// Fallback for older browsers.
const bytes = window.crypto.getRandomValues( new Uint8Array( 16 ) );
bytes[ 6 ] = ( bytes[ 6 ] & 0x0f ) | 0x40; // version 4
bytes[ 8 ] = ( bytes[ 8 ] & 0x3f ) | 0x80; // variant 10
const hex = Array.from( bytes, ( b ) => b.toString( 16 ).padStart( 2, '0' ) ).join( '' );
Comment on lines +89 to +94
$endpoint = defined( 'RTGODAM_ANALYTICS_BASE' ) ? RTGODAM_ANALYTICS_BASE : 'https://analytics.godam.io';
$api_key = get_option( 'rtgodam-api-key', '' );
$account_token = get_option( 'rtgodam-account-token', 'unverified' );
$site_url = home_url();
$from = $request->get_param( 'from' );
$to = $request->get_param( 'to' );
@github-actions
Copy link
Copy Markdown

🔍 WordPress Plugin Check Report

❌ Status: Failed

📊 Report

🎯 Total Issues ❌ Errors ⚠️ Warnings
17 3 14

❌ Errors (3)

📁 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.
📁 lib/class-godam-frappe-dispatch-installer.php (2 errors)
📍 Line 🔖 Check 💬 Message
302 PluginCheck.CodeAnalysis.WriteFile.PluginDirectoryWrite Plugin folders are deleted when upgraded. Do not save data to the plugin folder using unzip_file(). Detected usage of constant WP_PLUGIN_DIR. Use wp_upload_dir() to get the uploads directory path or save to the database instead.
347 PluginCheck.CodeAnalysis.WriteFile.PluginDirectoryWrite Plugin folders are deleted when upgraded. Do not save data to the plugin folder using copy_dir(). Detected usage of constant WP_PLUGIN_DIR. Use wp_upload_dir() to get the uploads directory path or save to the database instead.

⚠️ 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/25/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/25/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

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.

3 participants