Add tutorial: live viewer profiles with Signals media tracking - #1893
Add tutorial: live viewer profiles with Signals media tracking#1893jborlase-snowplow wants to merge 7 commits into
Conversation
A Signals counterpart to the Kafka live viewer profiles accelerator. The Kafka version needs Snowbridge, Kafka, a Java consumer, DynamoDB, a WebSocket back-end, and local Docker or Terraform; this one needs a tracker, a Signals attribute group, and a thin dashboard. Five pages: the comparison and prerequisites, the React video page with the media plugin, the `viewer_profile` stream attribute group and its service, and the dashboard built on the Node.js SDK's `getBatchServiceAttributes`. Verified against a live trial pipeline with real media events driven in a browser. Notable behaviours documented in the pages: * `seconds_watched` reads `last` of the media `session` entity's `timePlayed`, which already accumulates, so summing would multiply-count every ping. It is scoped to a media session and resets on reload, while the `ads_skipped` counter accumulates over the `domain_sessionid`. * The media plugin's `MediaType` enum is declared in its type definitions but not exported at runtime, so the page passes the `'video'` string. * `getBatchServiceAttributes` returns a columnar response with no identifier column, so rows map from the request's `identifiers` order. * Publishing is not instant and a published attribute group version is immutable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
documentation | 0a36cba | Commit Preview URL Branch Preview URL |
Jul 31 2026, 10:43 AM |
Style and writing reviewOverall this is a well-written accelerator: terminology is accurate ( 1. The companion repo link is a 404 (
|
Aggregate viewer metrics at the video level as well as the session level. A custom attribute key reads the media player's label, which the video page sets to the video's ID, and a second attribute group counts active viewers, distinct viewers, and skipped ads across every session watching a title. A service can only reference attribute groups that share an attribute key, so the two groups get a service each and the back-end makes one batch call per service. The Python definitions are now a single script that publishes the key, both groups, and both services together, passing the group objects straight to Service rather than hand-written name and version dicts. Also, from review: - Drop the Kafka comparison table for an Architecture section with a Mermaid diagram, and drop the companion repository link: every file is inline - Define the attribute group with the Python SDK directly, instead of starting in Console and cancelling, and remove the screenshots of the flow that is no longer instructed - Move the session registration step ahead of the back-end section, and fold the credentials into it - Style fixes: capitalized prerequisites, bold reserved for UI elements, lead-ins before bullet lists, and neutral phrasing Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Recreating an attribute group at the same name and version resumes the existing counters rather than starting from zero, which is worth knowing before you test the counts repeatedly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Pushed 🤖 Generated with Claude Code |
Offer a single paste-able prompt that produces the same Signals configuration as the Python SDK path: the custom video_id attribute key, both attribute groups, and one service per attribute key. The SDK path stays as written, since the dashboard reads the names it creates. The prompt works with any MCP-capable assistant connected to the Snowplow MCP server, or with the Snowplow Assistant in Console. A note explains that new definitions are saved as drafts, so the reader reviews the configuration before publishing it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Pushed Equivalence was verified for real, two ways: the MCP-built and SDK-built configurations' canonical registry JSON diff to identical (sole exception: Reviewer notes: the Console Assistant variant is mentioned, not walked (no UI claims made); no cross-link to the in-flight signals-mcp tutorial yet — add one in the new section and the conclusion when that PR merges; page 3 now sits at 7 H2s against the 3–5 guideline (declared, restructure if you prefer). 🤖 Generated with Claude Code |
Published tutorials shouldn't narrate the Console and API errors hit while verifying them, or how long anything took in those runs. * Page 2: state the media type strings as an instruction instead of an import failure, without the package version. * Page 3: keep one-service-per-attribute-key as the design statement it is, minus the 422 text; state group immutability without the 400 text; drop the delete-and-republish aside about stored values, which nothing else on the pages relies on; drop the publish-wait timing while keeping the wait itself, since values are empty until the definitions land. * Page 4: turn the registration note into the ordering rule the reader needs, and the troubleshooting list into positive checks on service names, credentials, and event ordering. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Pushed 🤖 Generated with Claude Code |
|
Claude (@claude) review please |
Writing quality reviewComments below are limited to things worth changing; the voice, second-person framing, and terminology are otherwise in good shape. Page structure
Headings
Wording and formatting
|
Product-owner directives: - Page 1 no longer frames the requirement as a "full pipeline" that rules out Snowplow Micro. It now asks for a Snowplow account and pipeline, keeping the free-trial pointer. - Removes the media-type-strings, "Why this group is defined in code", and "The media player entity has no ID field" panels. The label-to-video-ID fact survives as one prose sentence, since the custom attribute key depends on it. - Moves the AI-assistant section above the Python on page 3, and drops the two rationale paragraphs after the prompt. Review round: - Splits the attribute verification steps into their own page, renumbering the positions after it, and converts the last two page-3 notes to prose. - Adds a Snowplow implementation summary to the architecture section, listing the events and entities the demo generates. - Renames two headings, links the Console URL on first mention only, splits the over-length frontmatter descriptions, and drops a duplicated instruction to start the back-end first. - Adds Node.js and Python to the tutorial's technologies. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Pushed
🤖 Generated with Claude Code |
Page 3 mixed the two ways of creating the definitions into one linear flow: the AI-assistant section sat between the shared design and the Python, and ended by telling the reader to skip the rest of the page. Restructure it into two parallel route sections. The shared design now comes first in full, including the per-video conceptual paragraphs that were interleaved with the Python, so that the AI route's review step has something to check against. Then `## Define using the AI assistant` and `## Define using the Python SDK`, with the SDK flow's four steps nested as H3s and each route publishing on its own. The lead-in link points at the renamed AI section, and the page drops from 6 H2s to 4. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Pushed 🤖 Generated with Claude Code |
Note
The companion-repo merge blocker is resolved: the accelerator is now fully self-contained — every file is provided inline and the (formerly 404) repository link has been removed. One process point for reviewers:
tutorial-requirements/README.mdsays all source code must be on GitHub; the product owner has waived this for an inline-complete accelerator — confirm, or amend the requirement text.What changed?
New tutorial
tutorials/signals-live-viewer-profiles/(5 pages + 3 images): instrument video playback with the media tracking plugin, define session-level viewer attributes AND per-video audience metrics (customvideo_idattribute key) with the Python SDK, and build a live-viewers dashboard ongetBatchServiceAttributes.Why?
Fills the media-tracking + real-time-profiles gap in Signals tutorial coverage.
Reviewer guidance
active_viewers: 2; the dashboard screenshot matches a 3-session/2-video assertion round).media_player2-0-0 has no content ID —labelcarries the stable video ID (alternative documented).seconds_watcheduseslastnotsum(the session entity already accumulatestimePlayed); the push-state page folded into the conclusion (Node SDK can't subscribe to interventions).🤖 Generated with Claude Code