analytics: add Marlin SDK and migrate dropdown Heap markers#25133
analytics: add Marlin SDK and migrate dropdown Heap markers#25133dvdksn wants to merge 1 commit into
Conversation
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>
✅ 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.
| # TODO: replace placeholder endpoints with the canonical Marlin | ||
| # ingestion URLs from the data-platform team. | ||
| endpoint: | ||
| prod: https://REPLACE-ME.marlin.docker.com |
There was a problem hiding this comment.
[HIGH] REPLACE-ME placeholder endpoints will break production analytics ingestion
Both endpoint.prod and endpoint.stage are set to literal placeholder hostnames (https://REPLACE-ME.marlin.docker.com and https://REPLACE-ME.marlin.staging.docker.com). Because these are non-empty strings, the {{- if and $apiKey $endpoint -}} guard in head.html evaluates to truthy, so window.__marlinConfig will be emitted in production/staging builds with these values. The Marlin SDK will be initialized and will attempt to POST all analytics events to a non-functional hostname — silently failing to ingest any data from the moment this is deployed.
The PR description already flags this as a TODO. These values must be replaced with the canonical ingestion URLs from the data-platform team before merging, or the endpoint values should be left empty so the guard suppresses initialization entirely until the real endpoints are available.
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