squirrelscan
GitHub

VideoObject schema: required props and duration format

A page with an embedded video and no VideoObject markup, or markup missing thumbnailUrl, uploadDate or an ISO 8601 duration. squirrel checks both.

What VideoObject schema is

VideoObject is the schema.org type for a video. It names the video with name and description, points at a still with thumbnailUrl, dates it with uploadDate, and locates the file with contentUrl for the video itself or embedUrl for a player.

duration is typed as an ISO 8601 duration, which starts with P and puts a T before any time component: PT1H30M for ninety minutes, PT45S for forty-five seconds. A plain number of seconds or a 1:30:00 clock string is not valid. The markup describes a video present on the page, so it belongs on the watch page rather than on an index of videos.

What squirrel checks

The rule reads every script[type="application/ld+json"] on the page, flattens each one so a node nested in an @graph wrapper counts the same as a top-level node, and keeps the first VideoObject node from the last script that contains one, matching either a plain @type or an @type array. It also looks for a <video> element, or an <iframe> whose src contains youtube or vimeo. It emits one to three checks:

  • video-schema: with no VideoObject node and a video element present, it warns with the message Page has video but no VideoObject schema and the value Add schema for video rich results. With no VideoObject node and no video element it reports at info status with the message No VideoObject schema found. Either way no further checks run.
  • video-required: warns with the message VideoObject missing required properties and lists the missing names as items. The required set is name, description, thumbnailUrl and uploadDate. When all four are present it passes with VideoObject has required properties.
  • video-recommended: emitted only when at least one of duration, contentUrl and embedUrl is absent, at info status, with the message VideoObject could include recommended properties.
  • video-duration: emitted only when duration is a string that does not begin with PT. It warns with the message Duration should use ISO 8601 format and the value Got: <value>, expected: PT1H30M.

The duration check tests the PT prefix and nothing else, so PTbanana passes and a valid date-only duration such as P1D is reported as malformed. A duration given as a number rather than a string is not checked at all. Every property test is a truthiness test rather than a presence test, so a property present but empty, 0 or false counts as missing. A <video> element is detected whatever domain it plays from; only the iframe match is restricted to src values containing youtube or vimeo, so a third-party player under another domain does not count as video on the page.

How to fix it

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "VideoObject",
  "name": "Setting up the build cache",
  "description": "A six-minute walkthrough of the cache configuration.",
  "thumbnailUrl": "https://example.com/thumbs/build-cache.jpg",
  "uploadDate": "2026-03-14T09:30:00Z",
  "duration": "PT6M12S",
  "embedUrl": "https://www.youtube.com/embed/abc123"
}
</script>

Put it in the <head> of the page the video plays on, and generate duration from the source file rather than typing it.

The common false positive is a video loaded by a script after page load. squirrel reads the HTML the server sent unless browser rendering is on, so the element is not there and the page reports No VideoObject schema found instead of warning about missing markup.

Rule IDschema/video
CategoryStructured Data
ScopePer-page
Severitywarning
Weight5/10

Enable / disable

Disable this rule

[rules]
disable = ["schema/video"]

Disable all Structured Data rules

[rules]
disable = ["schema/*"]

Enable only this rule

[rules]
enable = ["schema/video"]

enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.

Structured data findings ship in every audit next to the core SEO, performance and agent experience rules. See Fix SEO issues with AI for how an agent works through a report.

References

Check your site

Run squirrel audit https://example.com and open the Structured Data section of the report. Each video page lists the properties it is missing. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

Type to search…

↑↓ navigate↵ openesc close