How to Add VideoObject Schema Markup for YouTube Embeds
Embedded YouTube videos don't pass their schema to your page. Here's a copy-paste VideoObject JSON-LD that earns you video rich results.
Embedding a YouTube video on your page does not give you video rich results in Google Search. The VideoObject schema that YouTube has on its own page stays on youtube.com — it does not transfer to yours. If you want the video thumbnail, duration, and title to appear in Google's video carousel or inline video results, you need to add VideoObject JSON-LD directly to your page.
This guide shows you exactly what to include, where to get the values, and how to validate the result.
Why your YouTube embed doesn't help with video rich results
When Google crawls an embedded <iframe>, it sees a reference to a URL on youtube.com. The VideoObject markup on that YouTube page gets attributed to YouTube's domain, not yours. Your page gets credit for hosting an embed, but not for publishing a video.
Google's video rich results — the thumbnail + duration chips that appear in search — require VideoObject schema to be present on the same page that ranks. That means you need to declare it yourself, even when the video lives on YouTube.
This is the same principle that applies to all structured data: schema markup lives on the page that should benefit from it.
The complete VideoObject JSON-LD
Here is a working example you can adapt:
{
"@context": "https://schema.org",
"@type": "VideoObject",
"name": "How to Do Keyword Research for a New Blog",
"description": "A step-by-step walkthrough of keyword research using free tools, covering search intent, competition analysis, and building a content plan.",
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
"uploadDate": "2025-11-14",
"duration": "PT8M45S",
"embedUrl": "https://www.youtube.com/embed/dQw4w9WgXcQ",
"contentUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"publisher": {
"@type": "Organization",
"name": "Your Site Name",
"logo": {
"@type": "ImageObject",
"url": "https://yoursite.com/logo.png"
}
}
}
Drop this in a <script type="application/ld+json"> tag in the <head> of the page containing the embed. If you're on Next.js, see how to add schema markup to Next.js App Router for the right placement. For WordPress without a plugin, the same JSON-LD approach applies — the FAQ schema guide for WordPress covers how to add raw JSON-LD to a WordPress page.
Field-by-field breakdown
name — The video title. This is what Google shows as the headline in video rich results. It should match the actual YouTube video title.
description — A summary of the video content. Aim for 50–200 characters. This doesn't need to match the YouTube description verbatim, but it should accurately represent the content.
thumbnailUrl — A publicly accessible image URL. For YouTube videos, the pattern is:
https://i.ytimg.com/vi/{VIDEO_ID}/maxresdefault.jpg— full HD thumbnail (1280×720), not always availablehttps://i.ytimg.com/vi/{VIDEO_ID}/hqdefault.jpg— 480×360, always available
Google requires at least one thumbnail with a minimum size of 60×30 pixels, but larger is better. Use maxresdefault.jpg and fall back to hqdefault.jpg if it returns a 404.
uploadDate — The date the video was published, in ISO 8601 format: YYYY-MM-DD. Use the original YouTube publish date, not the date you added the embed to your page.
duration — ISO 8601 duration format. The pattern is PT{H}H{M}M{S}S. Examples:
- 30 seconds →
PT30S - 4 minutes 30 seconds →
PT4M30S - 1 hour 12 minutes →
PT1H12M
This is one of the most common sources of validation errors. See the mistakes section below.
embedUrl — The https://www.youtube.com/embed/{VIDEO_ID} URL. This is the src you're already using in your <iframe>.
contentUrl — The canonical watch URL: https://www.youtube.com/watch?v={VIDEO_ID}. Google uses this to verify the video is real and accessible.
How to pull thumbnail and duration from the YouTube oEmbed API
Rather than hardcoding these values, you can fetch them once at build time using YouTube's oEmbed endpoint.
https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v={VIDEO_ID}&format=json
This returns a JSON object with title, thumbnail_url, and author_name. It does not return duration — for duration you need the YouTube Data API v3 or you can parse it from the page HTML.
The practical build-time approach for a static site generator:
<!-- In a build script or SSG data fetch -->
<!-- 1. Fetch oEmbed for title and thumbnail -->
<!-- GET https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=VIDEO_ID&format=json -->
<!-- 2. Use the YouTube Data API v3 for duration -->
<!-- GET https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=VIDEO_ID&key=YOUR_KEY -->
<!-- contentDetails.duration returns ISO 8601 already — use it directly -->
The Data API's contentDetails.duration field returns the value in ISO 8601 format (PT4M30S), so you can pass it straight into your schema without conversion.
Validating with Google's Rich Results Test
After adding the JSON-LD:
- Go to Google's Rich Results Test.
- Paste your page URL or the raw HTML.
- Look for "Video" in the detected structured data.
- If you see errors, they will identify which field is missing or malformed.
A green "Video" result means Google can parse your markup. It does not guarantee a video rich result will appear — Google still decides based on content quality and relevance — but it confirms the markup is valid.
For systematic validation across multiple pages, check Search Console under Enhancements → Videos once Google has crawled the updated pages. This report surfaces any field-level issues Google encountered at scale. For a full guide to interpreting these errors, see how to fix schema markup validation errors.
Common mistakes
Wrong duration format. 4:30 is not valid. 4M30S is not valid. The correct format is PT4M30S. The PT prefix is required. Leaving it off causes a type mismatch error in the Rich Results Test.
Missing thumbnailUrl. This is a required field. Without it, Google will not generate a video rich result regardless of how complete the rest of the markup is.
Using the playlist URL as embedUrl. The embed URL must point to the individual video (/embed/VIDEO_ID), not a playlist or channel page.
Stale uploadDate. Some CMS setups pull the current date rather than the original publish date. Use the YouTube video's publish date. Google cross-references this against YouTube's own data.
contentUrl pointing to the embed URL. These are two different fields for two different purposes. embedUrl is the iframe source. contentUrl is the direct video URL a user can open in a browser. Don't use the same value for both.
Omitting duration entirely. Duration is not technically required, but Google lists it as "recommended" and it directly affects the chip that shows in video rich results (the timestamp display). Skip it and you lose that feature.
What rich results you can expect
When VideoObject schema is valid and Google decides to use it, your video listing in search can show:
- A thumbnail image next to the result
- The video duration as a badge
- The video title as a linked headline
These appear in both standard web results (as an inline video block) and in the dedicated Video tab. Pages that have this markup and rank for informational queries tend to see click-through rate improvements because the thumbnail stands out visually in the SERP.
Adding VideoObject schema is one of the lower-effort wins in the schema markup category — the data is already on YouTube, you just need to surface it on your page.