Skip to content
Home » Reference » Content & Media Event Schema: The Complete Reference

Content & Media Event Schema: The Complete Reference

A complete reference for content and media analytics. All events — from page engagement to video completion — with parameters, data types, and data layer examples you can copy into your tracking plan.

Content sites live and die by engagement metrics. But most teams track nothing beyond page views. That tells you what people clicked on — not what they actually consumed. Did they read the article or bounce after the headline? Did they watch 10 seconds of your video or the full 8 minutes? This reference gives you a structured event schema that turns “visitors” into measurable engagement data.

I’ve used this schema across news publishers, corporate blogs, and media platforms in Europe. It works for any content-driven site — whether you’re monetizing through ads, subscriptions, or lead generation from your content.

Content Engagement Funnel

Content analytics tracks users through four engagement levels. Each level has distinct events that map to specific content performance metrics.

Level Key Events Business Metric
Reach page_view, content_impression Traffic, impressions
Consumption scroll_depth, read_complete, video_progress Engagement rate, avg. consumption
Interaction content_share, comment_posted, reaction_added Social amplification, community
Conversion newsletter_subscribe, paywall_hit, subscription_started Subscriber rate, revenue

Page Engagement Events

Page views tell you someone arrived. Engagement events tell you they stayed. The gap between the two is where most content analytics fails.

Event Parameters Type When It Fires
scroll_depth percent_scrolled number User scrolls past threshold (25, 50, 75, 100)
content_type string
content_id string
word_count number
read_complete content_id string User reaches end of article content
content_type string
time_on_content number
word_count number
time_on_content engaged_seconds number Fires at intervals (30s, 60s, 120s, 300s)
content_id string
content_visible boolean
content_impression content_id string Content card visible in viewport (lists, feeds)
content_title string
list_position number
list_name string

The content_type parameter is your segmentation key. Use consistent values: article, guide, case_study, news, tutorial, landing_page, or blog_post. This lets you compare engagement across content formats without separate events for each.

For scroll_depth, fire at 25% intervals. Avoid tracking every pixel — it creates noise and burns through GA4’s event quotas. The 25/50/75/100 pattern gives you enough granularity to spot drop-off points. When I set this up for a tech publisher in Berlin, we discovered that 70% of readers dropped off before 50% scroll on long-form articles — which led to restructuring content with key takeaways at the top.

Important: the content_visible parameter on time_on_content distinguishes active reading from tab-in-background. Use the Page Visibility API to track whether the tab is actually focused. Without this, your time metrics will be inflated by users who opened your article and switched to another tab.

Data Layer Example: Scroll Depth

window.dataLayer.push({
  "event": "scroll_depth",
  "percent_scrolled": 50,
  "content_type": "article",
  "content_id": "post-1234",
  "word_count": 2400
});

Video Tracking Events

Video is the hardest content type to track well. The challenge isn’t firing events — it’s firing them consistently across YouTube embeds, self-hosted players, and third-party platforms. This schema works with any player that exposes JavaScript events.

Event Parameters Type When It Fires
video_start video_title string User initiates video playback
video_id string
video_provider string
video_duration number
is_autoplay boolean
video_progress video_title string Video reaches 25%, 50%, 75% mark
video_id string
percent_watched number
video_duration number
video_complete video_title string Video reaches 95%+ of duration
video_id string
video_duration number
watch_time number
video_pause video_title string User pauses playback
percent_watched number
video_seek video_title string User jumps to different position
seek_from number
seek_to number

Use video_provider to distinguish between player types: youtube, vimeo, wistia, html5, or jwplayer. This matters because YouTube embeds fire events differently than self-hosted HTML5 players, and your GTM triggers need to account for both.

Fire video_complete at 95%, not 100%. Most users skip the last few seconds — especially when an end screen or outro appears. Setting the threshold at 95% gives you a more accurate completion rate. The watch_time parameter (actual seconds watched, excluding paused time) is more valuable than video_duration for measuring real engagement.

The is_autoplay parameter on video_start is critical. Without it, autoplay views inflate your start counts and destroy your start-to-complete ratio. Always separate autoplay from user-initiated plays in your reports.

Data Layer Example: Video Progress

window.dataLayer.push({
  "event": "video_progress",
  "video_title": "GA4 Migration Walkthrough",
  "video_id": "dQw4w9WgXcQ",
  "video_provider": "youtube",
  "percent_watched": 50,
  "video_duration": 480
});

Audio & Podcast Events

Audio tracking follows the same pattern as video but with podcast-specific parameters. If you host episodes on your site or embed players from Spotify, Apple Podcasts, or a custom player, these events capture listening behavior.

Event Parameters Type When It Fires
audio_start audio_title string User initiates audio playback
audio_id string
audio_type string
audio_duration number
episode_number number
audio_progress audio_title string Audio reaches 25%, 50%, 75%
percent_listened number
audio_complete audio_title string Audio reaches 95%+ of duration
audio_id string
listen_time number
audio_speed_change playback_speed number User changes playback speed
audio_title string

Use audio_type to distinguish between podcast_episode, audiobook, music, or voice_article. The audio_speed_change event is surprisingly useful — when a significant portion of listeners use 1.5x or 2x speed, it often signals that your content could be more concise.

Social Sharing & Interaction Events

Sharing events measure content amplification — when readers become distributors. These are the events that tie content quality to organic reach.

Event Parameters Type When It Fires
content_share share_method string User clicks a share button
content_id string
content_type string
content_title string
copy_link content_id string User copies article URL
copy_source string
comment_posted content_id string User submits a comment
comment_length number
is_reply boolean
reaction_added reaction_type string User clicks like, bookmark, or emoji
content_id string
text_selected selected_text_length number User highlights text (engagement signal)
content_id string

Use share_method values like twitter, linkedin, facebook, email, whatsapp, or native_share (for the browser’s Web Share API). The copy_link event captures dark social — people who share by pasting URLs directly into Slack, email, or messages. In my experience, copy-link sharing accounts for 40-60% of all shares on B2B content, yet most analytics setups miss it entirely.

The text_selected event is a lightweight engagement signal — people who highlight text are actively reading and often preparing to quote or reference your content. Don’t overtrack it: fire once per selection, and only when the selection is longer than 20 characters to avoid noise from accidental clicks.

Newsletter & Subscription Events

For content businesses, email subscribers and paid subscribers are the conversion events that map directly to revenue and audience growth.

Event Parameters Type When It Fires
newsletter_subscribe subscribe_location string User submits email for newsletter
newsletter_name string
content_id string
newsletter_unsubscribe newsletter_name string User unsubscribes (server-side)
days_subscribed number
paywall_hit content_id string User encounters paywall/gate
content_type string
paywall_type string
articles_read number
subscription_started plan_name string User starts paid subscription
plan_price number
currency string
billing_period string
subscription_cancelled plan_name string User cancels paid subscription
cancel_reason string
days_subscribed number

Use subscribe_location to track which placements convert: inline, end_of_article, popup, sidebar, exit_intent, or header_bar. Combined with content_id, you can see which specific articles drive the most newsletter signups.

The paywall_hit event is essential for metered paywall models. Track articles_read to see how many free articles users consume before hitting the wall — and how that number correlates with conversion to paid. Use paywall_type values like hard, metered, freemium, or registration_wall.

Data Layer Example: Newsletter Subscribe

window.dataLayer.push({
  "event": "newsletter_subscribe",
  "subscribe_location": "end_of_article",
  "newsletter_name": "weekly_digest",
  "content_id": "post-1234"
});

Search & Navigation Events

Internal search and navigation events reveal what users want to find — and whether your content architecture helps or hinders discovery.

Event Parameters Type When It Fires
internal_search search_term string User submits a search query
results_count number
search_location string
search_result_click search_term string User clicks a search result
result_position number
result_content_id string
category_view category_name string User browses a category/tag page
content_count number
related_content_click source_content_id string User clicks a recommended article
target_content_id string
recommendation_type string

The internal_search event with results_count = 0 is a gold mine for content strategy. These zero-result searches tell you exactly what your audience wants but can’t find. Export them monthly and use them to prioritize new articles.

Complete Event Map

Here’s every content and media event at a glance, organized by engagement level with recommended GA4 key event status.

Level Event Name Source Key Event?
Reach content_impression Client No
Consumption scroll_depth Client No
read_complete Client Yes
time_on_content Client No
video_start Client No
video_progress Client No
video_complete Client Yes
video_pause Client No
video_seek Client No
audio_start Client No
audio_progress Client No
audio_complete Client Yes
audio_speed_change Client No
Interaction content_share Client No
copy_link Client No
comment_posted Client No
reaction_added Client No
text_selected Client No
Navigation internal_search Client No
search_result_click Client No
category_view Client No
related_content_click Client No
Conversion newsletter_subscribe Client Yes
newsletter_unsubscribe Server No
paywall_hit Client No
subscription_started Client/Server Yes
subscription_cancelled Server No

Key events should be reserved for actions that represent genuine content engagement milestones or business value. Mark read_complete, video_complete, audio_complete, newsletter_subscribe, and subscription_started as key events. Everything else stays as regular events — valuable for analysis but not conversions.

GTM Implementation Guide

Here’s how to set up the core content tracking events in Google Tag Manager.

Event GTM Tag Name Trigger Type Notes
scroll_depth GA4 Event – scroll_depth Scroll Depth Set 25, 50, 75, 100 thresholds
read_complete GA4 Event – read_complete Element Visibility Target: end-of-article marker element
video_start GA4 Event – video_start YouTube Video / Custom Event Use built-in YouTube trigger or dataLayer
video_progress GA4 Event – video_progress YouTube Video / Custom Event Set 25, 50, 75 progress thresholds
video_complete GA4 Event – video_complete YouTube Video / Custom Event Use Complete status or 95% threshold
content_share GA4 Event – content_share Click – All Elements Filter by share button class/data attribute
newsletter_subscribe GA4 Event – newsletter_subscribe Custom Event (dataLayer) Fire on success callback from email provider
internal_search GA4 Event – internal_search Form Submission / Custom Event Capture search term from input field

YouTube tracking tip: GTM has a built-in YouTube video trigger that handles start, progress, pause, and complete events automatically. Enable it in your trigger settings and you get video tracking with zero custom code. For non-YouTube players (Vimeo, Wistia, HTML5), you’ll need custom JavaScript that listens to the player’s API and pushes events to the data layer.

Parameter Reuse Strategy

Consistent parameter naming across all content events conserves your GA4 custom dimension slots and simplifies reporting.

Parameter Reused Across Example Values
content_id All content events post-1234, video-567, episode-89
content_type scroll_depth, read_complete, content_share, paywall_hit article, guide, case_study, news, tutorial
video_title video_start, video_progress, video_complete, video_pause, video_seek Human-readable video title
audio_title audio_start, audio_progress, audio_complete, audio_speed_change Human-readable audio/episode title
search_term internal_search, search_result_click User’s search query text

Five shared parameters cover 20+ events. The content_id parameter is the most important — it lets you join engagement data across event types. You can answer questions like “which articles that people read completely also generated the most newsletter signups?” by filtering on the same content_id.

Validation Checklist

Before going live with your content tracking, verify each item:

Implementation Checklist

  • scroll_depth fires only at 25% thresholds (not every pixel)
  • read_complete targets the correct end-of-content element (not page footer)
  • time_on_content pauses when tab is not visible (Page Visibility API)
  • video_start distinguishes autoplay from user-initiated plays
  • video_complete fires at 95%, not 100%
  • content_share captures the actual platform, not just “clicked share button”
  • newsletter_subscribe fires on success callback, not on form submit
  • internal_search logs zero-result searches (results_count = 0)
  • All content_id values are consistent across events for the same content
  • No PII leaks in search terms or content parameters
  • Test in GA4 DebugView across desktop and mobile

FAQ

Should I use GA4’s built-in scroll and video events or custom ones?

GA4’s enhanced measurement includes basic scroll (90% only) and YouTube video events. They’re a good start, but limited. The built-in scroll event fires at just one threshold. Custom scroll tracking at 25% intervals gives you much more granular data. For video, GA4’s enhanced measurement only handles YouTube — if you use other players, you need custom events anyway. I recommend disabling the built-in events and implementing custom ones for consistency.

How do I track read completion accurately?

Use GTM’s Element Visibility trigger pointed at an invisible marker element placed at the end of your article content — after the last paragraph, before comments or related posts. Set it to fire when 100% of the element is visible, with a minimum on-screen duration of 1 second. This prevents false completions from fast-scrolling users who zip past the bottom without reading.

What’s a good read completion rate for articles?

Average read completion rates vary widely by content type. News articles typically see 20-30%, long-form guides 15-25%, and tutorials or how-to content 30-45%. Don’t compare across types — compare within the same content format and similar word count. A 25% completion rate on a 5,000-word deep dive may be excellent, while the same rate on a 500-word news piece signals a problem.

How should I handle tracking across paginated content?

For paginated articles (multi-page or infinite scroll), treat each page/section as a separate scroll_depth context with the same content_id but different page_number parameter. Fire read_complete only when the user reaches the end of the final page. For infinite scroll feeds, use content_impression to track which items enter the viewport instead of scroll_depth.

Is tracking text selection a privacy concern?

Track the length of selected text, not the text itself. Recording actual highlighted text could capture PII if users select their own name, email, or sensitive content. The selected_text_length parameter gives you the engagement signal without the privacy risk. Under GDPR, this qualifies as non-essential tracking and requires consent in most implementations.

Further Reading


Lukas Meier
Lukas Meier

Product Analytics Specialist based in Munich. Helping teams implement clean, actionable analytics since 2015.

Leave a Reply

Your email address will not be published. Required fields are marked *