Enhanced JSON-LD VideoObject Schema for Improved SEO
Describe the problem to be solved
The current JSON-LD schema generated for video pages lacks several important properties that are already available in PeerTube's video metadata. This limits SEO potential and discoverability in search engines.
Current JSON-LD output example:
{
"@context": "http://schema.org",
"@type": "VideoObject",
"name": "Video Title",
"description": "Video description...",
"image": "https://instance.tld/lazy-static/previews/...",
"url": "https://instance.tld/w/videoId",
"embedUrl": "https://instance.tld/videos/embed/videoId",
"uploadDate": "2025-11-13T14:51:08.083Z",
"duration": "PT799S",
"thumbnailUrl": "https://instance.tld/lazy-static/previews/..."
}
Missing properties that PeerTube already tracks internally:
inLanguage- Video language (critical for multilingual SEO)interactionStatistic- View count, likes, dislikeskeywords- Video tagscaption- Reference to subtitle/caption files (VTT, SRT)author/creator- Channel/account informationcontentRating- NSFW statusdatePublished/dateModified- Publication datesaggregateRating- Like/dislike ratio as rating
These properties are essential for:
- Google Video Search results enrichment
- Better search engine understanding of content
- Improved discoverability for non-English content
- Accessibility compliance (caption references)
Describe the solution you would like
Enhance the JSON-LD VideoObject schema to include additional properties from the video metadata:
{
"@context": "http://schema.org",
"@type": "VideoObject",
"name": "Video Title",
"description": "Video description...",
"image": "https://instance.tld/lazy-static/previews/...",
"url": "https://instance.tld/w/videoId",
"embedUrl": "https://instance.tld/videos/embed/videoId",
"uploadDate": "2025-11-13T14:51:08.083Z",
"duration": "PT799S",
"thumbnailUrl": "https://instance.tld/lazy-static/previews/...",
// NEW PROPERTIES:
"inLanguage": "sv",
"keywords": ["tag1", "tag2", "tag3"],
"interactionStatistic": [
{
"@type": "InteractionCounter",
"interactionType": "http://schema.org/WatchAction",
"userInteractionCount": 3687
},
{
"@type": "InteractionCounter",
"interactionType": "http://schema.org/LikeAction",
"userInteractionCount": 245
},
{
"@type": "InteractionCounter",
"interactionType": "http://schema.org/DislikeAction",
"userInteractionCount": 12
}
],
"author": {
"@type": "Organization",
"name": "Channel Name",
"url": "https://instance.tld/c/channel_name"
},
"caption": [
{
"@type": "MediaObject",
"contentUrl": "https://instance.tld/lazy-static/video-captions/videoId-sv.vtt",
"encodingFormat": "text/vtt",
"inLanguage": "sv",
"name": "Swedish"
},
{
"@type": "MediaObject",
"contentUrl": "https://instance.tld/lazy-static/video-captions/videoId-en.vtt",
"encodingFormat": "text/vtt",
"inLanguage": "en",
"name": "English"
}
],
"datePublished": "2025-11-13T17:00:29.000Z",
"dateModified": "2025-11-14T10:30:00.000Z",
"contentRating": "General Audience",
"publisher": {
"@type": "Organization",
"name": "Instance Name",
"url": "https://instance.tld"
}
}
Implementation suggestions:
- Language (
inLanguage): Map fromvideo.language.idfield - Keywords: Map from
video.tagsarray - View count: Map from
video.views - Likes/Dislikes: Map from
video.likesandvideo.dislikes - Author: Map from
video.account(orvideo.channel) - Captions: Iterate over
video.captions.dataarray and generate caption objects with proper language codes and URLs - Content Rating: Map from
video.nsfw(e.g., "General Audience" if false, "Mature" if true) orvideo.nsfwFlags - Dates: Use
video.publishedAt,video.originallyPublishedAt,video.updatedAt
Optional/Advanced enhancement:
Include transcript property when captions are available. This would require fetching the VTT/SRT content and converting to plain text:
"transcript": "Full transcript text extracted from caption file..."
This is extremely valuable for SEO as search engines can index the entire spoken content of videos.
Describe alternatives you have considered
-
Plugin-based solution: Create a plugin that overrides the JSON-LD generation. However, this is complex and requires ongoing maintenance with each PeerTube version.
-
Server-side template modification: Manually edit PeerTube source code. Not sustainable for upgrades.
-
Nginx sub_filter injection: Inject additional JSON-LD via web server. Technically complex and error-prone.
-
External pre-rendering service: Use services like Prerender.io. Costly and doesn't solve the underlying data enrichment issue.
All alternatives are inferior to native implementation as they require additional maintenance, introduce complexity, and may break with updates.
Use case
We find that videos from PeerTube instances are generally poorly indexed. There is a wealth of metadata and even full transcriptions in multiple languages, but still some more work needed to make it appear in Google search results. Despite having OpenGraph and Twitter Card meta tags, our JSON-LD schema is missing critical information that would improve our visibility in Google Video Search results.
Specific SEO benefits:
- Videos in non-English languages get properly categorized (
inLanguage) - Popular videos rank higher due to social proof (
interactionStatistic) - Topic relevance improved through keywords
- Accessibility and inclusion through caption references
- Voice search optimization through transcript inclusion
AI Assistant Discoverability:
Proper SEO indexing is increasingly important for content discovery beyond traditional search engines. AI assistants like ChatGPT, Claude, Grok, and Perplexity rely on web search results to provide users with current information. When PeerTube videos are properly indexed with rich structured data (JSON-LD), they become discoverable by these AI tools. This means users asking AI assistants questions about specific topics can be directed to relevant PeerTube content. With enhanced schema markup including language, keywords, and transcripts, AI systems can better understand and recommend video content to their users. This represents a significant opportunity for PeerTube instances to reach audiences through emerging AI-powered discovery channels, not just traditional search engines.
Additional context
- The sitemap.xml already contains much of this data (
<video:view_count>,<video:tag>, etc.), but the JSON-LD on individual pages does not - Google's Rich Results Test specifically looks for these properties: https://search.google.com/test/rich-results
- Schema.org VideoObject documentation: https://schema.org/VideoObject
- This enhancement would benefit all PeerTube instances, especially those competing with YouTube for search visibility
Related issues
- #6210 - Google Search indexing does not recognize the video as main content
- #1080 - SEO improvements (general SEO discussion)
- #553 - Adding a robots.txt file
Thank you for considering this enhancement! This would significantly improve the discoverability of PeerTube content in search engines and help the platform compete more effectively with centralized video platforms.
I'd like to add a few notes, if you don't mind.
I browsed YouTube and downloaded a schema for one of the videos. After examining several links, I found that keywords are added in
in addition to the schema.
Another thing is the headings.
The video title is primarily added in
<H1>
The phrase "Other videos" or "Similar videos" is primarily placed in
<H2>
Some words on the video page are also placed in
Comments - In this video - Description
<H2>
The titles of other or similar videos are primarily placed in
<H3>
I also found that some websites add
The schema file for one of the YouTube videos is attached.