JAVASCRIPTseobeginner

VideoObject Schema for Video SEO

Add Video structured data for Google Video rich results, carousels, and video search appearances

Faisal Yaqoob
#video#schema#seo#structured-data#json-ld#youtube#rich-snippets#google
Share this snippet:

Code

javascript
1// Single video schema - add to page <head> or before </body>
2const videoSchema = {
3 "@context": "https://schema.org",
4 "@type": "VideoObject",
5 "name": "How to Optimize WordPress Speed in 2025",
6 "description": "Step-by-step guide to improve your WordPress site loading time. Covers caching, image optimization, CDN setup, and Core Web Vitals fixes.",
7 "thumbnailUrl": "https://yoursite.com/images/video-thumbnail.jpg",
8 "uploadDate": "2025-12-25T08:00:00+00:00",
9 "duration": "PT12M30S", // ISO 8601: 12 minutes 30 seconds
10 "contentUrl": "https://yoursite.com/videos/wordpress-speed.mp4",
11 "embedUrl": "https://www.youtube.com/embed/VIDEO_ID",
12 "interactionStatistic": {
13 "@type": "InteractionCounter",
14 "interactionType": { "@type": "WatchAction" },
15 "userInteractionCount": 15000
16 },
17 "author": {
18 "@type": "Person",
19 "name": "Your Name",
20 "url": "https://yoursite.com/about"
21 },
22 "publisher": {
23 "@type": "Organization",
24 "name": "Your Channel Name",
25 "logo": {
26 "@type": "ImageObject",
27 "url": "https://yoursite.com/logo.png"
28 }
29 }
30};
31
32// Inject into page
33const script = document.createElement('script');
34script.type = 'application/ld+json';
35script.textContent = JSON.stringify(videoSchema);
36document.head.appendChild(script);

VideoObject Schema for Video SEO

Add VideoObject structured data to pages with embedded videos to appear in Google Video results, video carousels, and enriched search snippets. Video schema can increase click-through rates and drive traffic from Google's video tab.

Basic VideoObject Schema

// Single video schema - add to page <head> or before </body>
const videoSchema = {
  "@context": "https://schema.org",
  "@type": "VideoObject",
  "name": "How to Optimize WordPress Speed in 2025",
  "description": "Step-by-step guide to improve your WordPress site loading time. Covers caching, image optimization, CDN setup, and Core Web Vitals fixes.",
  "thumbnailUrl": "https://yoursite.com/images/video-thumbnail.jpg",
  "uploadDate": "2025-12-25T08:00:00+00:00",
  "duration": "PT12M30S", // ISO 8601: 12 minutes 30 seconds
  "contentUrl": "https://yoursite.com/videos/wordpress-speed.mp4",
  "embedUrl": "https://www.youtube.com/embed/VIDEO_ID",
  "interactionStatistic": {
    "@type": "InteractionCounter",
    "interactionType": { "@type": "WatchAction" },
    "userInteractionCount": 15000
  },
  "author": {
    "@type": "Person",
    "name": "Your Name",
    "url": "https://yoursite.com/about"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Your Channel Name",
    "logo": {
      "@type": "ImageObject",
      "url": "https://yoursite.com/logo.png"
    }
  }
};

// Inject into page
const script = document.createElement('script');
script.type = 'application/ld+json';
script.textContent = JSON.stringify(videoSchema);
document.head.appendChild(script);

Video with Clip Markup (Key Moments)

// Enable Key Moments in Google Search (timestamp links)
const videoWithClips = {
  "@context": "https://schema.org",
  "@type": "VideoObject",
  "name": "Complete WordPress SEO Tutorial",
  "description": "Full WordPress SEO guide covering on-page optimization, technical SEO, schema markup, and link building strategies.",
  "thumbnailUrl": "https://yoursite.com/images/seo-tutorial-thumb.jpg",
  "uploadDate": "2025-12-25T10:00:00+00:00",
  "duration": "PT45M00S",
  "embedUrl": "https://www.youtube.com/embed/VIDEO_ID",
  "hasPart": [
    {
      "@type": "Clip",
      "name": "Introduction to WordPress SEO",
      "startOffset": 0,
      "endOffset": 120,
      "url": "https://www.youtube.com/watch?v=VIDEO_ID&t=0"
    },
    {
      "@type": "Clip",
      "name": "Installing an SEO Plugin",
      "startOffset": 120,
      "endOffset": 360,
      "url": "https://www.youtube.com/watch?v=VIDEO_ID&t=120"
    },
    {
      "@type": "Clip",
      "name": "On-Page SEO Optimization",
      "startOffset": 360,
      "endOffset": 900,
      "url": "https://www.youtube.com/watch?v=VIDEO_ID&t=360"
    },
    {
      "@type": "Clip",
      "name": "Technical SEO Setup",
      "startOffset": 900,
      "endOffset": 1800,
      "url": "https://www.youtube.com/watch?v=VIDEO_ID&t=900"
    },
    {
      "@type": "Clip",
      "name": "Schema Markup Implementation",
      "startOffset": 1800,
      "endOffset": 2400,
      "url": "https://www.youtube.com/watch?v=VIDEO_ID&t=1800"
    }
  ]
};

Video in Article (Blog Post with Video)

// Combined Article + Video schema for blog posts with embedded videos
const articleWithVideo = {
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "How to Speed Up WordPress: Complete Guide",
  "description": "Learn how to optimize your WordPress site speed with our comprehensive video guide and written instructions.",
  "image": "https://yoursite.com/images/article-cover.jpg",
  "datePublished": "2025-12-25",
  "dateModified": "2025-12-25",
  "author": {
    "@type": "Person",
    "name": "Your Name"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Your Site",
    "logo": {
      "@type": "ImageObject",
      "url": "https://yoursite.com/logo.png"
    }
  },
  "video": {
    "@type": "VideoObject",
    "name": "WordPress Speed Optimization Tutorial",
    "description": "Watch this tutorial to learn how to speed up WordPress.",
    "thumbnailUrl": "https://yoursite.com/images/video-thumb.jpg",
    "uploadDate": "2025-12-25T08:00:00+00:00",
    "duration": "PT15M00S",
    "embedUrl": "https://www.youtube.com/embed/VIDEO_ID"
  }
};

WordPress PHP Implementation

/**
 * Auto-detect YouTube embeds and output VideoObject schema
 * Add to child theme functions.php
 */
function wp_video_schema_from_embeds() {
    if ( ! is_singular( 'post' ) ) {
        return;
    }

    global $post;
    $content = $post->post_content;

    // Match YouTube URLs in content
    $pattern = '/(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/';

    if ( ! preg_match( $pattern, $content, $matches ) ) {
        return;
    }

    $video_id = $matches[1];
    $thumbnail = get_the_post_thumbnail_url( $post->ID, 'full' );

    $schema = [
        '@context'     => 'https://schema.org',
        '@type'        => 'VideoObject',
        'name'         => get_the_title(),
        'description'  => wp_trim_words( get_the_excerpt(), 30 ),
        'thumbnailUrl' => $thumbnail ?: "https://img.youtube.com/vi/{$video_id}/maxresdefault.jpg",
        'uploadDate'   => get_the_date( 'c' ),
        'embedUrl'     => "https://www.youtube.com/embed/{$video_id}",
        'publisher'    => [
            '@type' => 'Organization',
            'name'  => get_bloginfo( 'name' ),
            'logo'  => [
                '@type' => 'ImageObject',
                'url'   => get_site_icon_url( 512 ),
            ],
        ],
    ];

    echo '<script type="application/ld+json">'
        . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES )
        . '</script>' . "\n";
}
add_action( 'wp_head', 'wp_video_schema_from_embeds' );

Duration Format Reference

// ISO 8601 Duration Format for video length
// PT = Period Time prefix

// Examples:
// PT30S        = 30 seconds
// PT5M         = 5 minutes
// PT1H         = 1 hour
// PT12M30S     = 12 minutes 30 seconds
// PT1H30M      = 1 hour 30 minutes
// PT2H15M30S   = 2 hours 15 minutes 30 seconds

// Helper function to convert seconds to ISO 8601
function secondsToISO8601(totalSeconds) {
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = totalSeconds % 60;

  let duration = 'PT';
  if (hours > 0) duration += hours + 'H';
  if (minutes > 0) duration += minutes + 'M';
  if (seconds > 0) duration += seconds + 'S';

  return duration;
}

Best Practices

  • Include thumbnailUrl — required for video rich results eligibility
  • Use ISO 8601 for duration — Google requires this exact format
  • Add Clip markup for Key Moments to get timestamp links in search
  • Set uploadDate — Google uses this to determine content freshness
  • Include embedUrl or contentUrl — at least one is required
  • Match visible content — video title and description must reflect what's on page

Features

  • Video Rich Results: Thumbnail and play button in search results
  • Key Moments: Timestamp links for long videos (Clip markup)
  • Video Carousel: Appear in Google's video carousel
  • Auto-Detection: WordPress function auto-detects YouTube embeds
  • Combined Schema: Nest video inside Article schema for blog posts
  • Cross-Platform: Works with YouTube, Vimeo, self-hosted, and any video source

Related Snippets