IFA EFC · Nashville · Nov 16–18Meet Videospan

Video Sitemaps

Help Google discover and understand video with video sitemap XML: required and optional tags, stable URLs, complete examples, and Next.js generation.

A video sitemap extends a standard XML sitemap with information about the videos on your pages. It helps Google discover new videos and understand their titles, thumbnails, players, media files, and availability—especially when normal crawling would miss them.

Use a video sitemap alongside, not instead of, a crawlable watch page and accurate VideoObject structured data. The watch page gives visitors and crawlers context; the sitemap gives them a reliable discovery feed.

When to use a video sitemap

Create a separate video sitemap or add video extension tags to an existing sitemap when you publish video landing pages, webinars, episodes, product demonstrations, or other substantial video content.

Do not add a video simply because an iframe appears on a page. The video should be relevant to the host page's main content. A small decorative clip or unrelated embed does not deserve its own video entry.

Google also supports mRSS for media discovery, but recommends video sitemaps. Use the format that fits your publishing system and keep it updated as media changes.

Required tags

Every video entry needs a watch-page <loc>, a <video:video> container, a thumbnail, a title, a description, and either a media-file URL or a player URL.

TagRequired valueBest practice
<loc>The canonical page where visitors watch the video.Use a stable, indexable landing-page URL. Do not point this to the MP4 or the iframe player.
<video:video>The container for one video on that page.Add one per video. Multiple videos on the same page need separate video:video elements and must all belong there.
<video:thumbnail_loc>The video's thumbnail image URL.Use a stable, high-quality, crawlable thumbnail that represents this specific video and matches thumbnailUrl elsewhere.
<video:title>The video title.Match the visible page title and VideoObject name. Escape XML entities or use CDATA.
<video:description>A description of up to 2,048 characters.Describe the actual video and stay consistent with the visible description and VideoObject description.
<video:content_loc>The actual video media bytes, when supplied directly.Use a supported media file at a stable, crawlable URL. This corresponds to VideoObject.contentUrl and must differ from the watch-page loc.
<video:player_loc>The player for the specific video, when using a player.Usually the iframe src. This corresponds to VideoObject.embedUrl and must differ from the watch-page loc. It is common for YouTube, Vimeo, and hosted players.

Optional tags

Optional fields add useful availability and discovery context. Include only values you can keep accurate.

TagMeaningFormat or guidance
<video:duration>Video duration.Whole seconds, from 1 to 28,800 (8 hours).
<video:publication_date>First publication time.W3C date or date-time, such as 2026-10-14T15:30:00-05:00.
<video:expiration_date>When the video stops being available.W3C date or date-time. Omit for non-expiring videos and update recurring videos at the same URL.
<video:restriction>Countries where the search result may appear.A space-delimited ISO country list with relationship="allow" or "deny". This affects search appearance, not playback access.
<video:platform>Device platforms where the search result may appear.Use web, mobile, or tv with relationship="allow" or "deny".
<video:requires_subscription>Whether a free or paid subscription is required.yes or no. Do not mark a public video as subscription-only.
<video:uploader>The person or organization that uploaded the video.Maximum 255 characters. The optional info URL must be on the watch-page domain.
<video:live>Whether the entry is a livestream.yes or no.
<video:tag>A short concept associated with the video.Repeat one element per tag, up to 32 tags. Use meaningful topics, not keyword lists.
<video:view_count>Reported number of views.Use truthful, current analytics if you maintain this field.
<video:rating>Average user rating.A value from 0.0 to 5.0 based on real ratings.
<video:family_friendly>SafeSearch availability.yes means available with SafeSearch on; no means only available with it off.

Avoid deprecated fields and copied examples that include them. In particular, Google's current documentation no longer lists video:category, video:gallery_loc, video:price, video:tvshow, or the old autoplay and allow_embed player attributes.

Complete XML example

Declare both the standard sitemap namespace and Google's video namespace. Escape ampersands and other XML entities in titles, descriptions, and URLs.

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
  <url>
    <loc>https://example.com/guides/brand-video</loc>
    <video:video>
      <video:thumbnail_loc>
        https://cdn.example.com/guides/brand-video-poster.jpg
      </video:thumbnail_loc>
      <video:title>Capture, Review &amp; Publish a Brand-Compliant Video</video:title>
      <video:description>
        A practical walkthrough of recording, review, rendering, and publishing
        a video that follows an organization's brand standards.
      </video:description>
      <video:content_loc>
        https://cdn.example.com/guides/brand-video.mp4
      </video:content_loc>
      <video:player_loc>
        https://player.example.com/embed/brand-video
      </video:player_loc>
      <video:duration>522</video:duration>
      <video:publication_date>2026-10-14T15:30:00-05:00</video:publication_date>
      <video:requires_subscription>no</video:requires_subscription>
      <video:live>no</video:live>
      <video:tag>brand standards</video:tag>
      <video:tag>video workflow</video:tag>
    </video:video>
  </url>
</urlset>

If the same watch page contains two substantial videos, keep one <url> and its single <loc>, then add a separate <video:video> element for each video. If each video has its own landing page, use a separate <url> for each page.

Keep the three URL types straight

Most video sitemap errors come from mixing up the page, player, and media file:

  • Watch page: <loc> and the canonical link on the page.
  • Player: <video:player_loc>, the iframe src, and VideoObject.embedUrl.
  • Media bytes: <video:content_loc> and VideoObject.contentUrl.

All referenced URLs must be accessible to Googlebot without a login and must not be blocked by robots.txt, a firewall, or another access rule. Use HTTP or HTTPS URLs that remain stable. Avoid short-lived signed URLs in sitemaps, posters, and structured data.

If you restrict media access to prevent abuse, verify legitimate Googlebot traffic rather than blocking every bot or returning different content to search engines and users.

Generate a video sitemap in Next.js

Next.js metadata sitemaps generate standard page entries. For video extension tags, create a custom route such as app/video-sitemap.xml/route.ts and generate the XML from the same content record used by the watch page and JSON-LD.

const videos = [
  {
    page: "https://example.com/guides/brand-video",
    player: "https://player.example.com/embed/brand-video",
    content: "https://cdn.example.com/guides/brand-video.mp4",
    thumbnail: "https://cdn.example.com/guides/brand-video-poster.jpg",
    title: "Capture, Review & Publish a Brand-Compliant Video",
    description:
      "A practical walkthrough of recording, review, rendering, and publishing.",
    duration: 522,
    published: "2026-10-14T15:30:00-05:00",
  },
];

function escapeXml(value: string) {
  return value.replace(/[<>&'\"]/g, (character) => {
    const entities: Record<string, string> = {
      "<": "&lt;",
      ">": "&gt;",
      "&": "&amp;",
      "'": "&apos;",
      '"': "&quot;",
    };
    return entities[character];
  });
}

export function GET() {
  const entries = videos
    .map(
      (video) => `
    <url>
      <loc>${escapeXml(video.page)}</loc>
      <video:video>
        <video:thumbnail_loc>${escapeXml(video.thumbnail)}</video:thumbnail_loc>
        <video:title>${escapeXml(video.title)}</video:title>
        <video:description>${escapeXml(video.description)}</video:description>
        <video:content_loc>${escapeXml(video.content)}</video:content_loc>
        <video:player_loc>${escapeXml(video.player)}</video:player_loc>
        <video:duration>${video.duration}</video:duration>
        <video:publication_date>${video.published}</video:publication_date>
      </video:video>
    </url>`,
    )
    .join("");

  const xml = `<?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
            xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
      ${entries}
    </urlset>`;

  return new Response(xml, {
    headers: {
      "Content-Type": "application/xml; charset=utf-8",
      "Cache-Control": "public, s-maxage=3600, stale-while-revalidate=86400",
    },
  });
}

A single sitemap can contain up to 50,000 URLs and must be no larger than 50 MB uncompressed. Split larger libraries and use a sitemap index. Generate entries from canonical content data so page metadata, sitemap entries, and JSON-LD cannot drift apart.

Validate and maintain

Test the XML before publishing it. A valid URL alone does not make the sitemap useful: every referenced page, player, thumbnail, and media file also needs to return the correct response to authorized crawlers.

Submit the sitemap in Google Search Console and reference it in robots.txt:

Sitemap: https://example.com/video-sitemap.xml

Use Search Console's sitemap and video indexing reports to inspect discovery problems. Update or remove entries when media is replaced, moved, expired, or removed. A stale sitemap repeatedly sends crawlers to broken or misleading destinations.

Video sitemap checks

0%
0 of 8 checks complete. Your progress is kept for this page session and is not uploaded.

Read Google's video sitemap documentation for the current tag definitions and examples, and review the Video Metadata chapter to align the sitemap with VideoObject markup.

Watch page
Player
Media bytes
<loc>https://example.com/guides/brand-video</loc>
<video:content_loc>https://cdn.example.com/guides/brand-video.mp4</video:content_loc>
<video:player_loc>https://player.example.com/embed/brand-video</video:player_loc>
URL mapping looks consistent · edit each URL to see how watch pages, players, and media bytes map to video sitemap tags.