VideoObject schema is structured data, usually a JSON-LD block, that tells search engines what a video on a page is: its title, thumbnail, upload date, length and file location. Google requires name, thumbnailUrl and uploadDate, and recommends description, duration and contentUrl. The markup helps Google understand the video; it does not guarantee a rich result. Videngine writes it into the page's HTML, beside the player and transcript, when it publishes a video.
What VideoObject schema is and what Google asks for
VideoObject is the schema.org type for a video, which schema.org defines as “a video file”, and Google reads it to understand the videos on a page and decide how to show them.
Google's video structured data documentation says videos can appear in the main results, Video mode, Google Images and Google Discover. These are its required and recommended properties as listed on 10 October 2026.
| Property | What it is | Example |
|---|---|---|
nameRequired | The video's title, unique to each video on your site | “Oak extending dining table: sizes, finish and care” |
thumbnailUrlRequired | The URL of the video's own thumbnail image file | https://www.example.com/videos/oak-table.jpg |
uploadDateRequired | When the video was first published, in ISO 8601, ideally with a timezone | 2026-10-08T09:30:00+01:00 |
descriptionRecommended | A description of the video, unique to each video | One or two sentences on what the video shows |
durationRecommended | The video's length in ISO 8601 duration format | PT1M12S (one minute, twelve seconds) |
contentUrlRecommended | The URL of the video file itself, not the page it sits on | https://www.example.com/videos/oak-table.mp4 |
embedUrlRecommended | The URL of the player for this video, used when you can't give contentUrl | https://www.example.com/player/oak-table |
creator (or author)Recommended | The person or organisation that made or published the video, with name and url | An Organization named “Example Furniture Ltd” |
expiresRecommended | When the video stops being available, if it does | 2027-01-31T23:59:00+00:00 |
hasPartRecommended | Clip objects marking important segments, used for key moments | A Clip called “Storing the leaf” from 0:40 |
interactionStatisticRecommended | Counts of watches, likes, comments or shares, if applicable | A WatchAction with a userInteractionCount |
regionsAllowed or ineligibleRegionRecommended | Where the video may or may not be shown; use one, not both | ["GB", "IE"] |
publicationRecommended | A BroadcastEvent, for livestreams and the LIVE badge | Only relevant to live video |
Without the required properties, Google says it may not be able to extract any information about the video. Transcript, width, height and inLanguage are valid schema.org properties not on Google's list; they still help other readers.
A complete JSON-LD example for a business page
A complete VideoObject block sits in a script element in the page's HTML, near the player it describes, and fills every field you can supply truthfully. Here is one for a furniture retailer's product page with a 72-second, self-hosted walk-through of a dining table:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "VideoObject",
"name": "Oak extending dining table: sizes, finish and care",
"description": "A 72-second walk-through of the oak extending dining table: both lengths, the oiled finish and where the extra leaf is stored.",
"thumbnailUrl": [
"https://www.example.com/videos/oak-table.jpg"
],
"uploadDate": "2026-10-08T09:30:00+01:00",
"duration": "PT1M12S",
"contentUrl": "https://www.example.com/videos/oak-table.mp4",
"width": 1920,
"height": 1080,
"inLanguage": "en",
"creator": {
"@type": "Organization",
"name": "Example Furniture Ltd",
"url": "https://www.example.com/"
},
"transcript": "This is the oak extending dining table. Closed, it is 140 centimetres long and seats four. Pull the ends apart, lift the leaf from underneath, and it reaches 190 centimetres and seats six. The top is finished with a hard-wax oil: wipe spills with a damp cloth and re-oil once a year."
}
</script>
The type application/ld+json tells parsers the contents are JSON-LD, not code to run. @context names the schema.org vocabulary and @type says this is a VideoObject.
name is the title a person would recognise, and description says what the viewer will see. Google asks for unique text in both for every video.
thumbnailUrl is an array because you may supply several images; Google's own example gives three shapes. One crawlable image is valid, and it should be the poster frame the player shows.
uploadDate is when the video was first published, ending in a UTC offset: +01:00 is British Summer Time. duration is ISO 8601: PT for a period of time, 1M for one minute, 12S for twelve seconds.
contentUrl points at the MP4 itself, which Google calls the most effective way for it to fetch video files. There is no embedUrl because the file is self-hosted; add one for a third-party player, a choice our comparison of YouTube and self-hosted video covers.
width, height and inLanguage describe the file, and creator names the business. transcript is trimmed here; in production it should match the visible transcript word for word, as our guide to video transcripts and captions explains. The glossary defines JSON-LD, ISO 8601 and the other terms.
Common video schema markup mistakes
Most broken video schema markup describes a video Google can't reach, or describes it in a format Google can't read.
| Mistake | What goes wrong | Fix |
|---|---|---|
| Markup for a video that isn't on the page | Google requires the video to be embedded on the page and the markup to match the actual video | Output VideoObject only where the player is |
| Thumbnail Google can't fetch | It must be reachable by Googlebot and Googlebot Images at a stable URL, not blocked by robots.txt or a login | A public BMP, GIF, JPEG, PNG, WebP, SVG or AVIF, at least 60x30 pixels |
| uploadDate without a timezone | Google falls back to Googlebot's timezone | End with an offset such as +01:00 or Z |
| Duration written as 1:12 or 72 | Not ISO 8601, which Google and schema.org specify | Write PT1M12S |
| One block for several videos, or shared values | Google asks for a unique name, description and thumbnail per video | One VideoObject per video |
| contentUrl pointing at the web page | Google says not to link to the page where the video lives | Point it at the video file |
| Markup injected by JavaScript | Google reads the rendered page; a crawler that reads only the server's HTML won't see it | Put the markup in the server's HTML |
Google's guide to JavaScript-generated structured data says Google Search can process structured data in the DOM when it renders the page. That covers Google only; markup in the server's HTML doesn't depend on any crawler running scripts, which matters for the readers in our note on video in AI search.
Watch pages and pages where video supports the content
Google keeps most video features for watch pages, pages whose main purpose is to show a single video; elsewhere, the same video is shown in fewer ways.
Google's video SEO best practices say that to be eligible for video features, including video results on the main results page, Video mode, key moments and the LIVE badge, you should create a dedicated watch page for each video, “if it makes sense for your business”. A video landing page is a watch page. A blog post reviewing an embedded video is not, because the video complements the page, and nor is a category page listing several videos of equal prominence.
Most business pages, like the dining table page above, are in the second group. That isn't a reason to leave the markup off: Google says a non-watch page can still appear as a text result and as a Google Images result with a video badge.
So the decision is a business one. If people would search for the video itself, such as a tour or a how-to, give it a page of its own. If it supports a listing, product or article, mark it up accurately and judge the page by its existing job.
How to test video structured data
Test the live URL with Google's Rich Results Test, then confirm in Search Console that Google rendered, indexed and accepted the video.
- Run the Rich Results Test on the published URL. Google's JavaScript guide recommends the URL input over pasted code. Fix any critical errors.
- Inspect the page with the URL Inspection tool. Check that the rendered HTML contains both the video element and the VideoObject block.
- Check the Video indexing report. It shows how many indexed watch pages contain an indexed video, and why other videos weren't indexed.
- Watch the rich result status report. Fix invalid items, inspect the live URL and request validation. Recheck after any template change.
- Give it time. Google suggests allowing several days for recrawling and reindexing.
A passing test proves the syntax, not the substance: Google notes the Rich Results Test can't catch markup that misdescribes the video.
How Videngine writes VideoObject when it publishes
Videngine's website publishing puts the video file, the player, the transcript and the VideoObject markup into your site in one commit.
A workspace connects the GitHub repository its website is built from, with “Connect with GitHub” or a fine-grained access token. Once a video is reviewed and approved in the studio, Publish makes a single commit that:
- adds the MP4, its poster JPG and a WebVTT caption track to the site, in /videos/ by default;
- writes into the page the video was made from an HTML5 video player with the poster and a metadata-only preload, and a readable transcript in a details element;
- adds VideoObject JSON-LD with name, description, thumbnailUrl, contentUrl, uploadDate, duration, width, height, inLanguage, transcript and publisher;
- keeps a video sitemap, video-sitemap.xml, and adds a Sitemap line to robots.txt. Our guide to video sitemaps explains what that file adds.
All of it is in the HTML the server sends, not injected by JavaScript, and because player and markup arrive together, the markup always describes a video on the page. One video per page means one VideoObject. Republishing replaces it in place; Remove takes video and markup out in one commit. A <!-- videngine --> comment marks where the video goes.
This works for sites whose pages are HTML files in the repository: static sites on Vercel, Netlify, Cloudflare Pages or GitHub Pages. The video SEO hub shows how markup, sitemap and transcript fit together.
When markup, or Videngine, isn't the fix
Markup describes a video Google can already reach; it can't make a page indexable, turn a supporting video into a watch page or promise a rich result.
Start with the page. Google's indexing requirements say the page must be indexed, and performing well in Search, before its video is considered.
If the video genuinely isn't the point of the page, accurate markup still helps Google understand it. Anything more is Google's decision: it says it does not guarantee that features using structured data will appear.
Videngine is the wrong tool in three cases:
- Framework-built sites. Website publishing doesn't support them yet. Add the JSON-LD to your page template instead.
- Videos you already have. Videngine publishes videos it made from your pages. For an existing library, your CMS, an SEO plugin or a developer is the direct route.
- A page of many videos. Videngine places one video per page. A gallery needs one VideoObject per video.
Questions about VideoObject schema
Is VideoObject schema required for a video to appear in Google?
No. Google can find videos referenced by video, embed, iframe or object elements on a page. It recommends providing metadata, and supports structured data, video sitemaps and Open Graph for that. If you do add VideoObject, the name, thumbnailUrl and uploadDate properties are required.
Does video structured data guarantee video rich results?
No. Google says it does not guarantee that features using structured data will show. Video features also depend on the page being indexed, on a crawlable thumbnail and, for most features, on a dedicated watch page.
Should I use JSON-LD for video or microdata?
Google's documentation shows both. JSON-LD keeps the whole description in one block that you can generate from your data without touching the player markup, which makes it easier to keep correct. Whichever you choose, the values must match the video on the page.
Do I need video schema markup for an embedded YouTube video?
Google still recommends structured data when a video plays in a third-party player. Use embedUrl for the player's URL, since you won't have a contentUrl for the file. The other required properties stay the same.
Can one page have more than one VideoObject?
Yes, with one VideoObject per video and a unique name, description and thumbnail for each. Google doesn't treat a page listing several videos of equal prominence as a watch page, so give a video its own page if you want video features for it.
Choose your next step
See how the markup fits into the rest of video SEO, then add the file that lists every video on your site.
Publish the video and its markup together.
Bring one page that already has a reason for a video. Review the video in the studio, then publish the player, transcript and VideoObject to your site in one commit.
Join the waitlist ↗Published by Videngine, a video rendering product built and run by Wall & Fifth. External links refer to the original documentation or product descriptions; examples are illustrative unless stated otherwise.