On this page:
This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
Created
updated

What is PodcastEpisode schema?

PodcastEpisode is the schema.org type for marking up a single installment of a podcast. It sits in the hierarchy as Thing > CreativeWork > Episode > PodcastEpisode, which means it inherits the full set of CreativeWork properties (author, datePublished, description, image) plus everything from Episode (episodeNumber, partOfSeason, partOfSeries). Each episode is a distinct entity, connected back to its parent PodcastSeries via the partOfSeries property.

Google deprecated Google Podcasts in 2024 and no longer maintains a dedicated rich result for PodcastEpisode, but the markup still drives entity recognition in search, powers podcast directories that consume schema.org JSON-LD, and gives AI answer engines (ChatGPT, Perplexity, Google AI Overviews) the structured payload they need to surface episodes in conversational answers.

Why this matters for AEO

Answer engines do not stream audio. When a user asks Perplexity "what did Naval Ravikant say about leverage on the Joe Rogan podcast," the engine retrieves text that describes the audio: episode metadata, show notes, and (when available) the transcript. PodcastEpisode schema is how that text becomes machine-readable. Without it, the AI engine has to scrape unstructured page content and guess at episode boundaries, hosts, and guests.

The single highest-leverage field in PodcastEpisode for AEO is transcript. Episodes with full transcripts in schema get cited in answer engine responses far more often than episodes without them, because the transcript is the only text representation of what was actually said. Show notes summarize. Transcripts retrieve.

Who created and maintains PodcastEpisode

The PodcastEpisode type is defined by schema.org, the joint vocabulary maintained by Google, Microsoft, Yahoo, and Yandex. Google previously published implementation guidance for podcast structured data through Google Search Central, but that documentation was removed when Google Podcasts shut down in April 2024. The schema.org vocabulary itself remains active and is the canonical reference for PodcastEpisode markup.

Adjacent standards governing values inside PodcastEpisode:

  • ISO 8601 for date formats (datePublished: "2024-09-15")
  • ISO 8601 duration for episode length (duration: "PT52M18S")
  • BCP 47 for language codes (inLanguage: "en-US")
  • MIME types for audio encoding in the associated AudioObject (encodingFormat: "audio/mpeg")

When to use PodcastEpisode

Use PodcastEpisode on any web page representing a single podcast episode. This includes:

  • Episode detail pages on a podcast's own website
  • CMS template pages for episode collections
  • Show notes pages that correspond to one specific episode
  • Embedded episode pages on Substack, Ghost, or other publishing platforms

Do not use PodcastEpisode for:

  • The podcast landing page (use PodcastSeries instead)
  • Standalone audio that is not part of a podcast series (use AudioObject)
  • A list of episodes or episode archive page (use CollectionPage with each episode referenced inside)

Field hierarchy

PodcastEpisode inherits over 60 properties from its parent types. In practice, a strong implementation uses 8 to 12 core fields plus a nested AudioObject for the audio file itself.

Essential fields

The minimum viable set. Without these the episode entity has nothing to anchor to.

  • @type: Always PodcastEpisode.
  • @id: Stable URI used as the entity identifier. Other schemas (PodcastSeries, AudioObject) reference this to declare relationship.
  • name: Episode title as it appears on the page and in podcast directories.
  • url: Canonical URL of the episode page on the site.
  • datePublished: ISO 8601 release date.
  • partOfSeries: Reference to the parent PodcastSeries, ideally via @id.

Recommended fields

Add these immediately after the essential set. They give AI engines and directories the context to rank and retrieve the episode correctly.

  • description: Episode summary, same text as the show notes intro.
  • duration: ISO 8601 duration (PT52M18S = 52 minutes 18 seconds).
  • episodeNumber: Sequential position within the series or season.
  • image: Episode artwork or show cover, as an ImageObject with width and height.
  • associatedMedia: Nested AudioObject with contentUrl pointing to the actual audio file and encodingFormat set to the MIME type.
  • author: Host or hosts as Person objects, each with their own sameAs linking to social profiles.

High-leverage AEO fields

These properties carry disproportionate weight for AI search visibility but are routinely missed.

  • transcript: Full episode transcript as plain text. The single strongest signal for being cited in answer engine responses.
  • actor: Guests on the episode, as Person objects with sameAs references to their public profiles. Enables guest-based queries ("what did guest say about topic").
  • about: Subject matter of the episode, as Thing references. Use Wikidata URIs when available for entity disambiguation.
  • keywords: Topic tags describing the episode's subject matter.

Optional but useful

  • partOfSeason: Reference to a PodcastSeason when the show uses seasons.
  • seasonNumber: Integer season position.
  • inLanguage: BCP 47 language code.
  • publisher: The organization that produces the show, referenced by @id from the site's Organization schema.
  • contributor: Producers, editors, or other credited contributors.
  • thumbnailUrl: Smaller thumbnail variant of the artwork.

Format requirements

PodcastEpisode is published as JSON-LD inside a <script type="application/ld+json"> block. Placement should be the <head> of the individual episode page.

The @context must be https://schema.org. The full duration format is ISO 8601: PT prefix, hours with H, minutes with M, seconds with S. So a 1 hour 23 minute 45 second episode is PT1H23M45S. Omit any zero units (PT45M is valid for a 45-minute episode with no seconds component).

When publishing the episode alongside its parent series, wrap both entities in a @graph array so the partOfSeries reference resolves cleanly. The same applies to the AudioObject and Person references: declaring them inside @graph with explicit @id values is stronger than nesting them inline.

JSON-LD example

Minimal episode

The smallest viable PodcastEpisode markup. Use this only when richer data is unavailable.

{
  "@context": "https://schema.org",
  "@type": "PodcastEpisode",
  "@id": "https://example.com/podcast/episode-12#episode",
  "name": "Why CRO and SEO fight each other",
  "datePublished": "2026-05-15",
  "duration": "PT52M18S",
  "url": "https://example.com/podcast/episode-12",
  "partOfSeries": {
    "@type": "PodcastSeries",
    "name": "The Example Show"
  }
}

Real brand example: Lex Fridman Podcast

The schema below mirrors the structure used by Lex Fridman Podcast episode pages, with the episode connected to its series, audio file, host, and guest.

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "PodcastSeries",
      "@id": "https://lexfridman.com/podcast/#series",
      "name": "Lex Fridman Podcast",
      "url": "https://lexfridman.com/podcast/",
      "webFeed": "https://lexfridman.com/feed/podcast/",
      "author": {
        "@type": "Person",
        "@id": "https://lexfridman.com/#host"
      }
    },
    {
      "@type": "Person",
      "@id": "https://lexfridman.com/#host",
      "name": "Lex Fridman",
      "url": "https://lexfridman.com",
      "sameAs": [
        "https://en.wikipedia.org/wiki/Lex_Fridman",
        "https://x.com/lexfridman",
        "https://www.youtube.com/@lexfridman"
      ]
    },
    {
      "@type": "PodcastEpisode",
      "@id": "https://lexfridman.com/naval-ravikant#episode",
      "name": "Naval Ravikant: Happiness, Wealth, and Wisdom",
      "url": "https://lexfridman.com/naval-ravikant/",
      "datePublished": "2019-06-04",
      "duration": "PT2H8M16S",
      "episodeNumber": 51,
      "description": "Naval Ravikant is an entrepreneur and angel investor. Conversation covers happiness, wealth, the nature of leverage, and the practice of clear thinking.",
      "partOfSeries": { "@id": "https://lexfridman.com/podcast/#series" },
      "author": { "@id": "https://lexfridman.com/#host" },
      "actor": {
        "@type": "Person",
        "name": "Naval Ravikant",
        "sameAs": [
          "https://en.wikipedia.org/wiki/Naval_Ravikant",
          "https://x.com/naval"
        ]
      },
      "associatedMedia": {
        "@type": "AudioObject",
        "@id": "https://lexfridman.com/naval-ravikant#audio",
        "contentUrl": "https://media.lexfridman.com/files/episode-51.mp3",
        "encodingFormat": "audio/mpeg",
        "duration": "PT2H8M16S"
      },
      "image": {
        "@type": "ImageObject",
        "url": "https://lexfridman.com/wordpress/wp-content/uploads/podcasts/lex_podcast_artwork.png",
        "width": 1400,
        "height": 1400
      },
      "inLanguage": "en"
    }
  ]
}

The structure to copy: PodcastSeries declared once with a stable @id, the host Person declared once and referenced from both the series and the episode, the AudioObject nested with its own @id, and the guest declared inline within actor. The partOfSeries reference points back to the series @id, which is what creates the connected graph.

With transcript

Adding the transcript turns the episode from a metadata blob into something AI engines can quote from directly. Even truncated transcripts (the first 5,000 words) carry significant weight.

{
  "@type": "PodcastEpisode",
  "@id": "https://example.com/podcast/episode-42#episode",
  "name": "How GraphQL Federation Works at Scale",
  "datePublished": "2024-11-20",
  "duration": "PT58M12S",
  "transcript": "Welcome back to the show. Today we are talking about GraphQL federation with our guest...",
  "partOfSeries": { "@id": "https://example.com/podcast/#series" }
}

How to implement in Webflow

Static episode pages

For one-off or hand-built episode pages, paste the full JSON-LD block into Page Settings, Custom Code, Head Code. Hardcode the episode metadata and audio URL. This is rarely the right pattern past 5 episodes.

CMS template pages

For any show running on Webflow CMS, the standard pattern is:

  1. Create an Episodes collection with fields for title, slug, description, published date, duration, episode number, audio file URL, transcript, and a reference field to the host Person.
  2. On the Episode template page, add an Embed element in the body containing the JSON-LD script block.
  3. Use the Add Field button inside the embed to inject CMS field references in place of static values. Common bindings: name from Title, datePublished from Published Date, duration from Duration, contentUrl from Audio File URL, transcript from the Transcript rich text field.
  4. The partOfSeries reference can point to a static @id hardcoded into the template since every episode belongs to the same show.

The transcript field is the most common point of failure. Webflow CMS rich text fields encode special characters automatically, which can break JSON parsing. Either store transcripts as plain text fields or strip the HTML before injecting into the schema.

With Schema HQ

Schema HQ manages PodcastEpisode schema across an entire Webflow show. The series, host, and AudioObject patterns are defined once in the dashboard. Each episode page automatically inherits the series and host references via @id linkage, and Schema HQ maps CMS fields to PodcastEpisode properties (including the AudioObject nesting) without manual JSON-LD construction in the Embed element.

Common mistakes

Missing partOfSeries link

❌ Episode with no series reference

{
  "@type": "PodcastEpisode",
  "name": "Episode 12",
  "datePublished": "2024-09-15",
  "duration": "PT45M"
}

✅ Episode linked to its parent series

{
  "@type": "PodcastEpisode",
  "name": "Episode 12",
  "datePublished": "2024-09-15",
  "duration": "PT45M",
  "partOfSeries": {
    "@type": "PodcastSeries",
    "@id": "https://example.com/podcast/#series",
    "name": "The Example Show"
  }
}

An episode without partOfSeries is an orphan. Directories and answer engines cannot connect it to the show, so it loses any branding and host attribution that comes from the series entity.

Duration in the wrong format

❌ Plain text duration

"duration": "45 minutes"

❌ Time-style duration

"duration": "00:45:00"

✅ ISO 8601 duration

"duration": "PT45M"

The duration field requires ISO 8601 format. Anything else is parsed as a string with no semantic meaning, which means filters like "show me podcasts under 30 minutes" cannot find the episode.

Audio URL on the wrong property

❌ Audio URL placed on the episode

{
  "@type": "PodcastEpisode",
  "url": "https://example.com/audio/episode-12.mp3"
}

✅ Audio URL on a nested AudioObject

{
  "@type": "PodcastEpisode",
  "url": "https://example.com/podcast/episode-12",
  "associatedMedia": {
    "@type": "AudioObject",
    "contentUrl": "https://example.com/audio/episode-12.mp3",
    "encodingFormat": "audio/mpeg"
  }
}

The url field on PodcastEpisode is the canonical web page URL, not the audio file. The audio file lives inside an associatedMedia AudioObject with contentUrl. Conflating these two breaks how directories and players consume the episode.

Inline series declaration repeated across every episode

❌ Full PodcastSeries duplicated on every episode page

"partOfSeries": {
  "@type": "PodcastSeries",
  "name": "The Example Show",
  "url": "https://example.com/podcast/",
  "description": "A show about...",
  "image": "https://example.com/cover.png",
  "author": { "@type": "Person", "name": "Jane Doe" }
}

✅ Series declared once, referenced by @id

"partOfSeries": {
  "@id": "https://example.com/podcast/#series"
}

The full PodcastSeries entity should be declared once (on the show's landing page or in a site-wide schema graph). Every episode then references the series via @id. Duplicating the full series block on each episode creates conflicting entity definitions if the data drifts.

Missing transcript on transcript-available episodes

❌ Transcript exists on the page but not in schema

The page renders a full transcript in HTML, but PodcastEpisode schema includes only the show notes intro.

✅ Transcript included in schema

{
  "@type": "PodcastEpisode",
  "transcript": "Full transcript text here, exactly as it appears on the page..."
}

The transcript is the highest-leverage AEO field on PodcastEpisode. If the transcript exists on the page, mirror it into the schema. Answer engines reading structured data rather than parsing HTML will only retrieve what is declared in JSON-LD.

Related types and fields

  • PodcastSeries: Parent entity that PodcastEpisode references via partOfSeries. Declared once on the show landing page.
  • AudioObject: The actual audio file, nested inside the episode via associatedMedia.
  • TVEpisode: Sibling type with parallel structure for television. Uses partOfSeason and partOfSeries the same way.
  • Person: Used for host (author) and guests (actor), with sameAs linking to verified profiles.
  • duration: ISO 8601 duration field shared with VideoObject, AudioObject, and other media types.
  • datePublished: Release date field shared across all CreativeWork subtypes.
  • author: Host or creator field shared across CreativeWork subtypes.

Schema HQ

Schema HQ manages PodcastEpisode markup across an entire Webflow show. The PodcastSeries, host Person, and AudioObject patterns are defined once in the dashboard, and every episode page inherits the references via @id linkage. Transcript fields, episode numbers, and durations map directly from Webflow CMS fields. No manual JSON-LD construction, no risk of drift between visible episode metadata and the schema declaration.

FAQ

Does PodcastEpisode schema replace an RSS feed?

No. RSS remains the canonical distribution format for podcasts, and Apple Podcasts, Spotify, and other directories ingest episodes exclusively from RSS feeds. PodcastEpisode schema is for the episode page on the show's own website. The two coexist: RSS distributes the audio to listening apps, PodcastEpisode schema makes the web page machine-readable for search engines and AI answer engines.

Should transcripts go in PodcastEpisode or in a separate Article schema?

Use the transcript property on PodcastEpisode directly. Wrapping a transcript in an Article and linking back to the episode adds an extra hop that retrieval systems may not follow. The transcript belongs to the episode, and declaring it inline on PodcastEpisode is the cleanest pattern.

How long should the duration value be allowed to drift from the actual audio file length?

The duration in PodcastEpisode schema should match the audio file length to within a second or two. Larger discrepancies signal data quality issues to consumers and reduce confidence in the rest of the metadata. If the audio file is re-edited after publication, update the schema along with the file.

Can PodcastEpisode work without an AudioObject?

Schema-validates yes, useful no. PodcastEpisode without an associated AudioObject is a metadata stub with no link to the actual audio. Directories that consume schema-based ingestion (a small but growing category) will skip episodes missing the audio reference. Always include the associatedMedia AudioObject when the audio file URL is available.

Where should episodeNumber start, at 0 or 1?

Episode numbers should start at 1 and match the publicly displayed episode number on the show. If the show uses seasons, pair episodeNumber with partOfSeason containing a PodcastSeason with seasonNumber. Episode 0 is a convention used by some shows for trailer or pilot content, in which case mirror what is shown publicly.

Ask AI about this property
Increase your AI visibility

Try AEO copilot

Try AEO copilot

Need help with schema on your site?

We implement structured data for Webflow sites — from audit to deployment.

Work with us

Work with us