analytics: add Marlin SDK and migrate dropdown Heap markers#25133
Conversation
✅ Deploy Preview for docsdocker ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🔴 CRITICAL
Here's the Marlin SDK analysis:
Summary
This PR initializes the @docker/marlin-sdk-web-public SDK on Docker Docs pages for production and staging environments. The SDK is constructed with a fixed site: "docs" identifier and selects Environment.STAGING or Environment.PROD based on the Hugo build environment. No track() calls are present in the diff — only SDK initialization and marlin-action attribute tagging on three toolbar buttons. The overall risk is High: both ingestion endpoints are literal REPLACE-ME placeholder hostnames that will be emitted to production builds, causing silent analytics failure from the moment the PR is deployed.
Concerns
1. REPLACE-ME placeholder endpoints in production config — High
In hugo.yaml (lines 153–154):
endpoint:
prod: https://REPLACE-ME.marlin.docker.com
stage: https://REPLACE-ME.marlin.staging.docker.comThe head.html template injects these values into window.__marlinConfig.endpoint, which marlin.js passes directly to new Marlin({ endpoint }). Because these are non-empty strings, the {{- if and $apiKey $endpoint -}} guard evaluates to truthy, so the config block will be emitted in production/staging builds. The SDK will attempt to POST all analytics events to a non-functional hostname — silently failing to ingest any data from deployment day.
Not a concern
- SDK initialization order:
window.marlinis assigned inmarlin.jsbefore anytrack()call site is reachable; no event is fired before init. - Event firing patterns: No
track()calls are present in the diff; no render-loop or unconditional firing risk. - Enum fields:
Environment.STAGING/Environment.PRODare SDK constants, not raw integers. - Timestamps: No timestamp fields are set in this diff.
- PII / identity fields: Not present; no
track()calls, no URL forwarding. - String kind correctness: Not applicable — no event payload fields are set.
- Required fields: Not applicable — no
track()calls. - UGC handling: Not applicable.
- Action discriminator: Not applicable.
- Companion doc alignment: Not applicable — no new events are introduced.
- data-heap-id → marlin-action migration: All three button attributes and the
querySelectorreference inmd-dropdown.htmlare consistently updated.
Recommendations
- Replace
https://REPLACE-ME.marlin.docker.comandhttps://REPLACE-ME.marlin.staging.docker.cominhugo.yamlwith the canonical ingestion URLs from the data-platform team before merging. As a safer alternative, leave the endpoint values empty (or omit them) until the real URLs are available — the{{- if and $apiKey $endpoint -}}guard will then correctly suppress SDK initialization.
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🟡 NEEDS ATTENTION
This PR cleanly integrates @docker/marlin-sdk-web-public for first-party pageview and click analytics. The SDK initialization is properly gated to prod/staging only, and the marlin-action attribute migration from data-heap-id is straightforward. One medium issue warrants attention before merge (see inline comment), and one informational note on the JavaScript fallback logic is included below.
Here's the Marlin SDK analysis:
Summary
This PR instruments the Docker Docs site with the Marlin Web SDK (@docker/marlin-sdk-web-public v0.2.0). It uses auto-click tracking via marlin-action HTML attributes on three markdown-dropdown buttons (ask-gordon-button, copy-markdown-button, view-markdown-button) and performs SDK initialization only when a prod or staging __marlinConfig block is present in the page. No explicit track() calls are made — all event emission is delegated to the SDK's auto-tracking machinery. The overall risk profile is low for PII and data-integrity concerns.
Concerns
1. Unresolved endpoint TODO — Medium
In hugo.yaml (lines 150–154):
# TODO: replace placeholder endpoints with the canonical Marlin
# ingestion URLs from the data-platform team.
endpoint:
prod: https://marlin-2.docker.com
stage: https://marlin-2-stage.docker.comThe TODO comment and unchecked PR checkbox both indicate the URLs have not been confirmed as the final canonical ingestion endpoints. If these are placeholders, analytics events will be silently dropped or misdirected after merge.
Not a concern
- PII / identity field sourcing: No URL, referrer,
window.location.href, or user-supplied values are forwarded to any tracking call. Auto-click tracking only captures themarlin-actionattribute value, which is a hardcoded constant. ✅ - String kind correctness: The
marlin-actionvalues (ask-gordon-button,copy-markdown-button,view-markdown-button) are hard-coded constants in the template, consistent withSTRING_KIND_FIXEDsemantics. ✅ - Required fields / format constraints: No explicit payload construction — all envelope fields (event_id, process_id, etc.) are SDK-managed. ✅
- Enum field usage:
Environment.STAGING/Environment.PRODare generated SDK enum constants, not raw integers. ✅ - Platform context alignment: SDK is initialized client-side (loaded via
<script defer>), consistent withPLATFORM_CONTEXT_WEB. ✅ - UGC handling: No user-generated content fields are populated. ✅
actiondiscriminator:marlin-actionattribute values are static constants defined in the template, not user input. ✅- Timestamps: No timestamp fields are set manually; SDK handles
logged_atautomatically. ✅ - Identity graph correctness: No identity fields (
account_id,hub_uuid, etc.) are populated. The SDK initializes without user identity. ✅ - Event firing patterns: SDK initialization is guarded by
if (config && config.apiKey && config.endpoint)— fires once on page load only. Auto-click events fire on user interaction, not in a render loop. ✅ - Companion doc alignment: No new explicit events are introduced; auto-tracked clicks use SDK-managed event types. No producer-authored companion docs required. ✅
Recommendations
- Resolve the endpoint TODO before merging. Confirm the canonical ingestion URLs with the data-platform team and remove the TODO comment.
- Note on environment fallback (low risk, no action required): The JS ternary
config.environment === 'staging' ? Environment.STAGING : Environment.PRODwould silently default to PROD for any unrecognized environment string, but the Hugo template guarantees only'prod'or'staging'are ever emitted, and the config block is suppressed entirely in all other environments. No action needed.
Introduces @docker/marlin-sdk-web-public for first-party pageview and click analytics, bundled into scripts.js via Hugo's existing js.Build pipeline. Config is emitted to window.__marlinConfig from head.html and gated to prod/staging only. Renames data-heap-id attributes on the markdown-dropdown buttons to marlin-action so they are picked up by the SDK's auto-click tracking. TODO: replace the REPLACE-ME endpoint placeholders in hugo.yaml with the canonical Marlin ingestion URLs from the data-platform team. TODO: heap.track() calls in youtube-script.html are left in place — the public SDK exposes no equivalent track() method, so video play/pause events cannot be migrated yet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
Introduces @docker/marlin-sdk-web-public for first-party pageview and
click analytics, bundled into scripts.js via Hugo's existing js.Build
pipeline. Config is emitted to window.__marlinConfig from head.html and
gated to prod/staging only.
Renames data-heap-id attributes on the markdown-dropdown buttons to
marlin-action so they are picked up by the SDK's auto-click tracking.
TODO: replace the REPLACE-ME endpoint placeholders in hugo.yaml with the canonical Marlin ingestion URLs from the data-platform team.
TODO: heap.track() calls in youtube-script.html are left in place — the public SDK exposes no equivalent track() method, so video play/pause events cannot be migrated yet.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com