Media & Streaming Event Spec
This page defines all standard events for media and streaming businesses on Datafly Signal — publishers, news sites, video-on-demand and live streaming platforms, and podcast players. It covers the full lifecycle: content discovery, engagement, video and audio playback, advertising, conversion (subscriptions and leads), and retention. Implement these events to enable accurate server-side delivery to advertising and analytics platforms.
Where a media event overlaps with a standard GA4 recommended event (search, view_item, sign_up, login, purchase, generate_lead), this spec reuses the GA4 name so existing Google Tag Manager implementations work as-is. Media-specific events follow Segment’s video and content tracking specs, using snake_case throughout.
All events are sent via datafly.track(). Properties are passed as a flat object in the second argument.
Never pass raw PII (email address, phone number, or full name) in track() properties. Identity is resolved server-side by Signal from first-party cookies. Pass opaque IDs such as content_id, author_id, or subscription_id only.
Content Discovery Events
These events describe how users find content — browsing feeds, searching, and filtering.
view_item_list
Fired when a user views a feed, category page, channel, or list of content items (articles, videos, podcasts).
datafly.track('view_item_list', {
item_list_id: 'channel-technology',
item_list_name: 'Technology',
items: [
{ item_id: 'art-90213', item_name: 'The State of Server-Side Tracking', index: 0, content_type: 'article', author_id: 'auth-12' },
{ item_id: 'art-90218', item_name: 'Why First-Party Data Wins', index: 1, content_type: 'article', author_id: 'auth-07' }
]
})| Property | Type | Required | Description |
|---|---|---|---|
item_list_id | string | Optional | Machine-readable identifier for the feed, channel, or category |
item_list_name | string | Optional | Human-readable name of the list being browsed |
items | array | Optional | Array of content items displayed in the list (see Items Array Schema) |
select_item
Fired when a user clicks a content item within a feed, list, or search results to open it.
datafly.track('select_item', {
item_list_id: 'channel-technology',
item_list_name: 'Technology',
items: [
{ item_id: 'art-90213', item_name: 'The State of Server-Side Tracking', index: 0, content_type: 'article' }
]
})| Property | Type | Required | Description |
|---|---|---|---|
item_list_id | string | Optional | Identifier of the list the item was selected from |
item_list_name | string | Optional | Name of the list the item was selected from |
items | array | Optional | Array containing the selected content item (see Items Array Schema) |
search
Fired when a user submits a search query for content.
datafly.track('search', {
search_term: 'first-party tracking',
results_count: 42
})| Property | Type | Required | Description |
|---|---|---|---|
search_term | string | Required | The search term entered by the user |
results_count | number | Optional | Number of results returned for the query |
view_promotion
Fired when a promotional unit, content recommendation rail, or hero placement becomes visible to the user.
datafly.track('view_promotion', {
promotion_id: 'rail-trending-now',
promotion_name: 'Trending Now',
creative_name: 'homepage-trending-rail',
creative_slot: 'homepage-hero'
})| Property | Type | Required | Description |
|---|---|---|---|
promotion_id | string | Optional | Identifier for the promotion or recommendation rail |
promotion_name | string | Optional | Human-readable name of the promotion |
creative_name | string | Optional | Name or URL of the creative asset shown |
creative_slot | string | Optional | Slot or placement where the promotion appeared |
select_promotion
Fired when a user clicks a promotional unit or recommendation.
datafly.track('select_promotion', {
promotion_id: 'rail-trending-now',
promotion_name: 'Trending Now',
creative_name: 'homepage-trending-rail',
creative_slot: 'homepage-hero'
})| Property | Type | Required | Description |
|---|---|---|---|
promotion_id | string | Optional | Identifier for the promotion or recommendation rail |
promotion_name | string | Optional | Human-readable name of the promotion |
creative_name | string | Optional | Name or URL of the creative asset shown |
creative_slot | string | Optional | Slot or placement where the promotion appeared |
Content Engagement Events
These events describe how users engage with an individual piece of content — articles, videos, podcasts, galleries.
content_viewed
Fired when a user opens a piece of content (article page, video detail page, podcast episode page). This is the primary content-consumption signal. Also accepted as view_item.
datafly.track('content_viewed', {
content_id: 'art-90213',
content_type: 'article',
content_title: 'The State of Server-Side Tracking',
content_category: 'Technology',
author_id: 'auth-12',
publish_date: '2026-06-20',
paywalled: false,
word_count: 1840
})| Property | Type | Required | Description |
|---|---|---|---|
content_id | string | Required | Unique identifier for the content item |
content_type | string | Optional | Type of content (e.g. article, video, podcast, gallery) |
content_title | string | Optional | Display title of the content |
content_category | string | Optional | Section, channel, or category the content belongs to |
author_id | string | Optional | Identifier of the author or creator |
publish_date | string | Optional | Publication date (ISO 8601) |
paywalled | boolean | Optional | Whether the content sits behind a paywall |
word_count | number | Optional | Word count (for text content) |
content_scrolled
Fired when a user reaches a scroll-depth milestone within an article or page. Fire once each at 25%, 50%, 75%, and 100%.
datafly.track('content_scrolled', {
content_id: 'art-90213',
content_type: 'article',
percent_scrolled: 50
})| Property | Type | Required | Description |
|---|---|---|---|
content_id | string | Required | Identifier of the content being read |
content_type | string | Optional | Type of content |
percent_scrolled | number | Optional | Scroll-depth milestone reached. One of: 25, 50, 75, 100 |
content_completed
Fired when a user finishes consuming a piece of content — reaching the end of an article or finishing a gallery.
datafly.track('content_completed', {
content_id: 'art-90213',
content_type: 'article',
time_spent: 312
})| Property | Type | Required | Description |
|---|---|---|---|
content_id | string | Required | Identifier of the completed content |
content_type | string | Optional | Type of content |
time_spent | number | Optional | Active time spent on the content in seconds |
content_shared
Fired when a user shares a content item to a social network, messaging app, or via a copied link.
datafly.track('content_shared', {
content_id: 'art-90213',
content_type: 'article',
content_title: 'The State of Server-Side Tracking',
share_method: 'twitter'
})| Property | Type | Required | Description |
|---|---|---|---|
content_id | string | Required | Identifier of the shared content |
content_type | string | Optional | Type of content |
content_title | string | Optional | Display title of the content |
share_method | string | Optional | Destination of the share (e.g. twitter, facebook, whatsapp, email, copy_link) |
content_liked
Fired when a user likes, upvotes, or reacts positively to a content item.
datafly.track('content_liked', {
content_id: 'art-90213',
content_type: 'article',
content_title: 'The State of Server-Side Tracking'
})| Property | Type | Required | Description |
|---|---|---|---|
content_id | string | Required | Identifier of the liked content |
content_type | string | Optional | Type of content |
content_title | string | Optional | Display title of the content |
content_saved
Fired when a user saves or bookmarks a content item to read or watch later.
datafly.track('content_saved', {
content_id: 'art-90213',
content_type: 'article',
content_title: 'The State of Server-Side Tracking',
list_name: 'Read Later'
})| Property | Type | Required | Description |
|---|---|---|---|
content_id | string | Required | Identifier of the saved content |
content_type | string | Optional | Type of content |
content_title | string | Optional | Display title of the content |
list_name | string | Optional | Name of the list or collection the content was saved to |
content_downloaded
Fired when a user downloads a content item for offline access — a PDF, an offline video, or a podcast episode.
datafly.track('content_downloaded', {
content_id: 'pod-signal-ep-041',
content_type: 'podcast',
content_title: 'Server-Side Tracking in 2026',
file_format: 'mp3'
})| Property | Type | Required | Description |
|---|---|---|---|
content_id | string | Required | Identifier of the downloaded content |
content_type | string | Optional | Type of content |
content_title | string | Optional | Display title of the content |
file_format | string | Optional | File format downloaded (e.g. mp3, mp4, pdf) |
comment_posted
Fired when a user posts a comment on a content item.
datafly.track('comment_posted', {
content_id: 'art-90213',
content_type: 'article',
comment_id: 'cmt-558210'
})| Property | Type | Required | Description |
|---|---|---|---|
content_id | string | Required | Identifier of the content commented on |
content_type | string | Optional | Type of content |
comment_id | string | Optional | Identifier of the posted comment |
Video Playback Events
These events describe the state of the media player. They are fired regardless of what content is loaded.
This spec distinguishes between two categories of video event:
Playback events (video_playback_*) describe the state of the media player — play, pause, buffer, seek. They are fired regardless of what content is loaded.
Content events (video_content_*) describe the specific piece of content being watched — the show, film, or clip. A single playback session may contain multiple content items (e.g. a playlist or episode queue).
Use session_id to correlate all events within the same viewing session. Generate a new session_id each time the player loads, not each time a new video starts.
video_played
Fired when a user starts a video — a lightweight, high-level “play” signal suitable for advertising platforms that expect a single video-start event. For full session telemetry, also emit video_playback_started.
datafly.track('video_played', {
session_id: 'vps-f3a9c2b1',
content_id: 'ep-s2e4-breaking-ground',
content_title: 'Breaking Ground — Season 2, Episode 4',
content_type: 'video',
total_length: 2740,
livestream: false
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Unique identifier for this playback session |
content_id | string | Optional | ID of the content being played |
content_title | string | Optional | Display title of the content |
content_type | string | Optional | Type of content (e.g. video, clip, trailer) |
total_length | number | Optional | Total duration of the content in seconds |
livestream | boolean | Optional | Whether this is a live stream |
video_playback_started
Fired when a user presses play and playback begins (or auto-play initiates). This is the first event in any detailed playback session.
datafly.track('video_playback_started', {
session_id: 'vps-f3a9c2b1',
content_asset_id: 'ep-s2e4-breaking-ground',
position: 0,
total_length: 2740,
bitrate: 4500,
quality: '1080p',
fullscreen: false,
sound: 80,
livestream: false
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Unique identifier for this playback session |
content_asset_id | string | Optional | ID of the content item currently loaded |
content_pod_id | string | Optional | ID of the content playlist or pod |
ad_asset_id | string | Optional | ID of an ad playing at session start (pre-roll) |
position | number | Optional | Playback position in seconds at start |
total_length | number | Optional | Total duration of the content in seconds |
bitrate | number | Optional | Current stream bitrate in kbps |
quality | string | Optional | Video quality label (e.g. 1080p, 720p, 480p, auto) |
fullscreen | boolean | Optional | Whether the player is in fullscreen mode |
sound | number | Optional | Volume level at start, expressed as 0–100 |
livestream | boolean | Optional | Whether this is a live stream |
video_playback_paused
Fired when playback is paused by the user.
datafly.track('video_playback_paused', {
session_id: 'vps-f3a9c2b1',
position: 483,
total_length: 2740
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
position | number | Optional | Playback position in seconds when paused |
total_length | number | Optional | Total duration of the content in seconds |
video_playback_resumed
Fired when playback resumes after a pause.
datafly.track('video_playback_resumed', {
session_id: 'vps-f3a9c2b1',
position: 483,
total_length: 2740
})Accepts the same properties as video_playback_paused.
video_playback_completed
Fired when the player reaches the end of the content and playback stops naturally.
datafly.track('video_playback_completed', {
session_id: 'vps-f3a9c2b1',
total_length: 2740
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
total_length | number | Optional | Total duration of the content in seconds |
video_playback_buffer_started
Fired when playback stalls and the player enters a buffering state.
datafly.track('video_playback_buffer_started', {
session_id: 'vps-f3a9c2b1',
position: 721
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
position | number | Optional | Playback position in seconds when buffering began |
video_playback_buffer_completed
Fired when buffering ends and playback resumes.
datafly.track('video_playback_buffer_completed', {
session_id: 'vps-f3a9c2b1',
position: 721
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
position | number | Optional | Playback position in seconds when buffering ended |
video_playback_seek_started
Fired when the user begins scrubbing or seeking to a new position in the timeline.
datafly.track('video_playback_seek_started', {
session_id: 'vps-f3a9c2b1',
seek_position: 1200
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
seek_position | number | Required | Target position in seconds the user is seeking to |
video_playback_seek_completed
Fired when the seek operation completes and playback resumes at the new position.
datafly.track('video_playback_seek_completed', {
session_id: 'vps-f3a9c2b1',
seek_position: 1200
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
seek_position | number | Optional | Position in seconds where playback resumed |
Video Content Events
These events describe the specific content item being played within a session.
video_content_started
Fired when a content item begins playing. In a playlist, fire this for each new item as it starts.
datafly.track('video_content_started', {
session_id: 'vps-f3a9c2b1',
asset_id: 'ep-s2e4-breaking-ground',
title: 'Breaking Ground — Season 2, Episode 4',
description: 'The team discovers an unexpected obstacle beneath the foundation.',
keywords: ['construction', 'documentary', 'engineering'],
season: '2',
episode: '4',
genre: 'Documentary',
programme: 'Breaking Ground',
publisher: 'Northfield Studios',
channel: 'Documentary',
livestream: false,
airdate: '2026-01-14',
total_length: 2740,
position: 0
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
asset_id | string | Optional | Unique identifier for this content item |
title | string | Optional | Display title of the content |
description | string | Optional | Short description or synopsis |
keywords | string[] | Optional | Topic or genre keywords |
season | string | Optional | Season number (for episodic content) |
episode | string | Optional | Episode number (for episodic content) |
genre | string | Optional | Genre classification |
programme | string | Optional | Parent show or series name |
publisher | string | Optional | Production company or content owner |
channel | string | Optional | Channel or category within the platform |
livestream | boolean | Optional | Whether this is live content |
airdate | string | Optional | Original broadcast or release date (ISO 8601) |
total_length | number | Optional | Total duration of the content in seconds |
position | number | Optional | Position in seconds where the content started playing |
video_content_completed
Fired when a content item finishes playing. For playlists, this fires before video_content_started fires for the next item.
datafly.track('video_content_completed', {
session_id: 'vps-f3a9c2b1',
asset_id: 'ep-s2e4-breaking-ground',
total_length: 2740
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
asset_id | string | Optional | Unique identifier for the completed content item |
total_length | number | Optional | Total duration of the content in seconds |
video_content_milestone
Fired when a user reaches a watch percentage milestone. Fire once each at 25%, 50%, and 75% completion. Do not fire at 100% — use video_content_completed instead.
datafly.track('video_content_milestone', {
session_id: 'vps-f3a9c2b1',
asset_id: 'ep-s2e4-breaking-ground',
position: 685,
milestone: 25
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
asset_id | string | Optional | Identifier of the content item |
position | number | Optional | Playback position in seconds at the milestone |
milestone | number | Optional | Milestone reached. One of: 25, 50, 75 |
Milestone events are useful for measuring engaged viewing. Use them in pipeline transformations to send custom audience signals — for example, sending users who reach the 75% milestone to a retargeting list.
Advertising Events
These events track ad impressions and interactions within the player and across the page.
ad_impression
Fired when an ad becomes viewable to the user — whether a video ad in the player or a display unit on the page. This is the canonical monetisation signal for publishers.
datafly.track('ad_impression', {
ad_unit_id: 'homepage-leaderboard',
ad_format: 'display',
placement: 'above-the-fold',
campaign_id: 'cmp-northedge-summer',
value: 0.012,
currency: 'GBP'
})| Property | Type | Required | Description |
|---|---|---|---|
ad_unit_id | string | Required | Identifier of the ad unit or placement |
ad_format | string | Optional | Ad format (e.g. display, video, native, audio) |
placement | string | Optional | Placement description (e.g. above-the-fold, in-feed, pre-roll) |
campaign_id | string | Optional | Identifier of the advertising campaign |
value | number | Optional | Estimated revenue for the impression |
currency | string | Optional | ISO 4217 currency code |
ad_clicked
Fired when a user clicks an ad.
datafly.track('ad_clicked', {
ad_unit_id: 'homepage-leaderboard',
ad_format: 'display',
campaign_id: 'cmp-northedge-summer'
})| Property | Type | Required | Description |
|---|---|---|---|
ad_unit_id | string | Required | Identifier of the ad unit clicked |
ad_format | string | Optional | Ad format (e.g. display, video, native, audio) |
campaign_id | string | Optional | Identifier of the advertising campaign |
video_ad_started
Fired when an ad begins playing within the player.
datafly.track('video_ad_started', {
session_id: 'vps-f3a9c2b1',
asset_id: 'ad-northedge-brand-001',
pod_id: 'pod-preroll-01',
type: 'pre-roll',
title: 'NorthEdge — Summer Collection',
publisher: 'NorthEdge',
total_length: 30,
position: 0,
load_type: 'linear'
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
asset_id | string | Optional | Unique identifier for the ad creative |
pod_id | string | Optional | Identifier for the ad break (pod) this ad belongs to |
type | string | Optional | Ad placement type. One of: pre-roll, mid-roll, post-roll |
title | string | Optional | Ad title or campaign name |
publisher | string | Optional | Advertiser or publisher serving the ad |
total_length | number | Optional | Duration of the ad in seconds |
position | number | Optional | Playback position within the content when the ad started |
load_type | string | Optional | Ad serving method. One of: linear (standard), dynamic (DAI) |
video_ad_completed
Fired when an ad plays through to completion without being skipped.
datafly.track('video_ad_completed', {
session_id: 'vps-f3a9c2b1',
asset_id: 'ad-northedge-brand-001',
pod_id: 'pod-preroll-01'
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
asset_id | string | Optional | Identifier for the completed ad |
pod_id | string | Optional | Identifier for the ad break |
video_ad_skipped
Fired when a user skips a skippable ad before it completes.
datafly.track('video_ad_skipped', {
session_id: 'vps-f3a9c2b1',
asset_id: 'ad-northedge-brand-001',
position: 6
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Playback session identifier |
asset_id | string | Optional | Identifier for the skipped ad |
position | number | Optional | Position in seconds within the ad at the point of skip |
Audio Events
audio_playback_started
Fired when audio playback begins — for music tracks, podcast episodes, or audio articles.
datafly.track('audio_playback_started', {
session_id: 'aps-9b3f21a0',
asset_id: 'pod-signal-ep-041',
title: 'Server-Side Tracking in 2026',
artist: 'The Datafly Podcast',
album: 'Season 3',
genre: 'Technology',
duration: 3180,
position: 0
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Unique identifier for this audio playback session |
asset_id | string | Optional | Unique identifier for the audio asset |
title | string | Optional | Track or episode title |
artist | string | Optional | Artist, host, or creator name |
album | string | Optional | Album, show, or series name |
genre | string | Optional | Genre classification |
duration | number | Optional | Total duration of the audio asset in seconds |
position | number | Optional | Playback position in seconds at start |
audio_playback_paused
Fired when audio playback is paused.
datafly.track('audio_playback_paused', {
session_id: 'aps-9b3f21a0',
position: 940
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Audio playback session identifier |
position | number | Optional | Playback position in seconds when paused |
audio_playback_completed
Fired when an audio asset plays through to the end.
datafly.track('audio_playback_completed', {
session_id: 'aps-9b3f21a0',
asset_id: 'pod-signal-ep-041',
duration: 3180
})| Property | Type | Required | Description |
|---|---|---|---|
session_id | string | Required | Audio playback session identifier |
asset_id | string | Optional | Identifier for the completed audio asset |
duration | number | Optional | Total duration of the audio asset in seconds |
podcast_subscribed
Fired when a user subscribes to a podcast show within the platform.
datafly.track('podcast_subscribed', {
show_id: 'show-datafly-podcast',
show_title: 'The Datafly Podcast'
})| Property | Type | Required | Description |
|---|---|---|---|
show_id | string | Required | Unique identifier for the podcast show |
show_title | string | Optional | Display title of the podcast show |
Conversion Events
These events capture the actions that turn an anonymous reader or viewer into a registered, subscribed, or monetised user. They are the highest-value signals to deliver server-side to advertising platforms.
sign_up
Fired when a user completes account registration.
datafly.track('sign_up', {
method: 'email'
})| Property | Type | Required | Description |
|---|---|---|---|
method | string | Optional | Registration method (e.g. email, google, apple) |
login
Fired when a user signs in to their account.
datafly.track('login', {
method: 'email'
})| Property | Type | Required | Description |
|---|---|---|---|
method | string | Optional | Login method (e.g. email, google, apple) |
generate_lead
Fired when a user submits a lead-generating form — a newsletter signup, gated content request, or content-download form.
datafly.track('generate_lead', {
lead_type: 'newsletter',
newsletter_id: 'weekly-briefing',
value: 2.50,
currency: 'GBP'
})| Property | Type | Required | Description |
|---|---|---|---|
lead_type | string | Optional | Type of lead captured (e.g. newsletter, gated_content, webinar) |
newsletter_id | string | Optional | Identifier of the newsletter or list subscribed to |
value | number | Optional | Estimated value of the lead |
currency | string | Optional | ISO 4217 currency code |
view_item
Fired when a user views a subscription, membership, or paywall offer page. Reuses the GA4 view_item name so paywall offers map cleanly to vendor ViewContent events.
datafly.track('view_item', {
currency: 'GBP',
value: 9.99,
items: [
{ item_id: 'plan-premium-monthly', item_name: 'Premium Monthly', item_category: 'subscription', price: 9.99 }
]
})| Property | Type | Required | Description |
|---|---|---|---|
currency | string | Optional | ISO 4217 currency code |
value | number | Optional | Price of the offer viewed |
items | array | Optional | Array containing the subscription or membership offer (see Items Array Schema) |
begin_checkout
Fired when a user starts the subscription or membership purchase flow.
datafly.track('begin_checkout', {
currency: 'GBP',
value: 9.99,
coupon: 'FIRST3FREE',
items: [
{ item_id: 'plan-premium-monthly', item_name: 'Premium Monthly', item_category: 'subscription', price: 9.99 }
]
})| Property | Type | Required | Description |
|---|---|---|---|
currency | string | Optional | ISO 4217 currency code |
value | number | Optional | Value of the subscription being purchased |
coupon | string | Optional | Promotion or coupon code applied |
items | array | Optional | Subscription or membership offer in the checkout (see Items Array Schema) |
purchase
Fired when a user completes a subscription purchase, membership upgrade, or one-off content payment. This is the most important conversion event — ensure it fires reliably.
datafly.track('purchase', {
transaction_id: 'SUB-10042',
value: 9.99,
currency: 'GBP',
coupon: 'FIRST3FREE',
items: [
{ item_id: 'plan-premium-monthly', item_name: 'Premium Monthly', item_category: 'subscription', price: 9.99, quantity: 1 }
]
})| Property | Type | Required | Description |
|---|---|---|---|
transaction_id | string | Required | Unique transaction identifier — used for deduplication |
value | number | Optional | Total amount charged |
currency | string | Optional | ISO 4217 currency code |
coupon | string | Optional | Promotion or coupon code applied |
items | array | Optional | Subscription or content items purchased (see Items Array Schema) |
Always send transaction_id on purchase events for deduplication. Platforms like Meta CAPI and GA4 use the transaction ID to prevent double-counting alongside browser-side events.
Retention Events
These events describe subscription lifecycle changes after the initial purchase — the core retention signals for a subscription media business.
subscription_renewed
Fired when a subscription successfully renews for another billing period.
datafly.track('subscription_renewed', {
subscription_id: 'sub-10042',
plan_id: 'plan-premium-monthly',
value: 9.99,
currency: 'GBP',
renewal_count: 4
})| Property | Type | Required | Description |
|---|---|---|---|
subscription_id | string | Required | Identifier of the subscription |
plan_id | string | Optional | Identifier of the plan or tier |
value | number | Optional | Amount charged for the renewal |
currency | string | Optional | ISO 4217 currency code |
renewal_count | number | Optional | Number of renewals to date |
subscription_cancelled
Fired when a user cancels their subscription.
datafly.track('subscription_cancelled', {
subscription_id: 'sub-10042',
plan_id: 'plan-premium-monthly',
reason: 'too_expensive'
})| Property | Type | Required | Description |
|---|---|---|---|
subscription_id | string | Required | Identifier of the cancelled subscription |
plan_id | string | Optional | Identifier of the plan or tier |
reason | string | Optional | Cancellation reason code (e.g. too_expensive, not_using, switching) |
Items Array Schema
Several events accept an items array — used for content lists and subscription offers. Each object in the array can include the following properties. The items[] array uses GA4-style field names. Signal’s server-side blueprints automatically transform these to vendor-specific formats (e.g., Meta’s contents[] with id/title fields).
| Property | Type | Description |
|---|---|---|
item_id | string | Content ID, SKU, or subscription plan ID |
item_name | string | Display name of the content item or offer |
item_category | string | Section, channel, or offer category (e.g. article, subscription) |
content_type | string | Type of content (e.g. article, video, podcast) |
author_id | string | Identifier of the author or creator |
price | number | Price of the offer (for subscription/membership items) |
quantity | number | Number of units (relevant for subscription quantity) |
index | number | Position in list (0-indexed, relevant in list/search contexts) |
currency | string | ISO 4217 currency code |
coupon | string | Item-level coupon or promotion code if applicable |
item_list_id | string | Identifier of the list the item was shown in |
item_list_name | string | Name of the list the item was shown in |
Vendor Mapping
The table below shows how Datafly Signal maps media events to the native event names expected by each vendor’s server-side API. Signal uses the GA4-style event names as its canonical format, and blueprints handle the transformation to vendor-specific payloads. (custom) indicates the vendor has no native equivalent, so Signal delivers a custom event of the same name.
| Signal Event | GA4 | Meta CAPI | TikTok Events API |
|---|---|---|---|
view_item_list | view_item_list | ViewContent | ViewContent |
select_item | select_item | ViewContent | ClickButton |
search | search | Search | Search |
view_promotion | view_promotion | (custom) | (custom) |
select_promotion | select_promotion | (custom) | (custom) |
content_viewed | view_item | ViewContent | ViewContent |
content_scrolled | scroll | (custom) | (custom) |
content_completed | (custom) | ViewContent | (custom) |
content_shared | share | (custom) | Share |
content_liked | (custom) | (custom) | (custom) |
content_saved | add_to_wishlist | AddToWishlist | AddToWishlist |
content_downloaded | (custom) | (custom) | Download |
comment_posted | (custom) | (custom) | (custom) |
video_played | video_start | ViewContent | ViewContent |
video_playback_started | video_start | ViewContent | ViewContent |
video_playback_paused | (custom) | (custom) | (custom) |
video_playback_resumed | (custom) | (custom) | (custom) |
video_playback_completed | video_complete | (custom) | (custom) |
video_playback_buffer_started | (custom) | (custom) | (custom) |
video_playback_buffer_completed | (custom) | (custom) | (custom) |
video_playback_seek_started | (custom) | (custom) | (custom) |
video_playback_seek_completed | (custom) | (custom) | (custom) |
video_content_started | video_start | ViewContent | ViewContent |
video_content_completed | video_complete | (custom) | (custom) |
video_content_milestone | video_progress | (custom) | (custom) |
ad_impression | ad_impression | (custom) | (custom) |
ad_clicked | select_content | (custom) | ClickButton |
video_ad_started | ad_impression | (custom) | (custom) |
video_ad_completed | (custom) | (custom) | (custom) |
video_ad_skipped | (custom) | (custom) | (custom) |
audio_playback_started | video_start | ViewContent | ViewContent |
audio_playback_paused | (custom) | (custom) | (custom) |
audio_playback_completed | video_complete | (custom) | (custom) |
podcast_subscribed | sign_up | Subscribe | Subscribe |
sign_up | sign_up | CompleteRegistration | CompleteRegistration |
login | login | (custom) | (custom) |
generate_lead | generate_lead | Lead | SubmitForm |
view_item | view_item | ViewContent | ViewContent |
begin_checkout | begin_checkout | InitiateCheckout | InitiateCheckout |
purchase | purchase | Subscribe | Subscribe |
subscription_renewed | (custom) | Subscribe | Subscribe |
subscription_cancelled | (custom) | (custom) | (custom) |