Youtube video embed reference skill
Video can improve engagement and extraction when it is relevant, current, and
by AgriciDaniel·MIT license·★ 2,219 Stars on the repo·GitHub ↗
Files of Youtube video embed reference
AgriciDaniel/
Show the full text197 lines
YouTube Video Embed Reference
Why YouTube Embeds Matter
Video can improve engagement and extraction when it is relevant, current, and high quality. Treat vendor correlation studies as directional, not as ranking requirements. Key data points:
- 0.737 correlation with AI visibility, the strongest single signal (Ahrefs 75K-brand study)
- Video citations in AI Overviews up 414% year-over-year (NP Digital Q1 2025, 10K+ AIO analysis)
- How-to video citations up 651%, visual demo citations up 592% (NP Digital)
- YouTube is cited 200x more than any other video platform by AI systems
Strongly prefer relevant YouTube embeds when a suitable video exists. Skip video when available videos are stale, low quality, off-topic, or would distract from the article.
Video Quality Criteria
Minimum Standards
| Criterion | Minimum | Preferred |
|---|---|---|
| Views | >1,000 | >10,000 |
| Like ratio | >90% | >95% |
| Recency | <3 years | <18 months |
| Channel subscribers | >1,000 | >10,000 |
| Duration | >3 minutes | 5-15 minutes |
| Captions | Present | Accurate/manual |
| Relevance | Title keyword match | Title + description match |
Quality Scoring Formula (0-100)
| Factor | Weight | Scoring Method |
|---|---|---|
| Relevance (title/description keyword match) | 35 pts | Exact keyword in title = 35, partial = 20, description only = 10 |
| View count (log scale) | 20 pts | log10(views) / log10(10M) * 20, capped at 20 |
| Recency (months since publish) | 20 pts | max(0, 20 - (months_old * 0.8)) |
| Channel authority (subscribers, log scale) | 15 pts | log10(subs) / log10(1M) * 15, capped at 15 |
| Engagement (like ratio) | 10 pts | (like_ratio - 0.80) / 0.20 * 10, capped at 10 |
Minimum score threshold: 50/100. Videos scoring below 50 should be skipped.
Embed Placement Strategy
| Position | Video Purpose | When |
|---|---|---|
| After introduction (before first H2 body) | Overview / explainer | Always place 1st video here |
| Mid-article (after 2nd or 3rd H2) | Tutorial / demo / how-to | If video shows a process |
| Before FAQ or conclusion | Summary or expert opinion | Optional 3rd video |
Placement Rules
- 2-3 videos per post (never more than 3)
- Minimum 500 words between video embeds
- Never place a video immediately before or after a chart
- Videos complement text; they never replace written content
Embed Code Patterns
Before rendering any embed, validate VIDEO_ID against YouTube's ID pattern and
escape title, channel, and description fields with html.escape(value, quote=True).
Reject untrusted javascript:, data:, and file: URLs.
MDX / Next.js (camelCase, srcDoc lazy loading)
<figure className="video-embed" style={{margin: '2.5rem 0', textAlign: 'center'}}>
<div style={{position: 'relative', paddingBottom: '56.25%', height: 0, overflow: 'hidden', maxWidth: '100%', borderRadius: '12px'}}>
<iframe
srcDoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href='https://www.youtube.com/embed/VIDEO_ID?autoplay=1'><img src='https://img.youtube.com/vi/VIDEO_ID/hqdefault.jpg' alt='VIDEO_TITLE_ESC'><span>►</span></a>"
style={{position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', border: 'none'}}
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
sandbox="allow-scripts allow-same-origin allow-presentation"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
title="VIDEO_TITLE_ESC"
aria-label="YouTube video: VIDEO_TITLE_ESC"
/>
</div>
<noscript>
<p><strong>Video:</strong> <a href="https://www.youtube.com/watch?v=VIDEO_ID">VIDEO_TITLE_ESC</a> by CHANNEL_NAME_ESC. DESCRIPTION_EXCERPT_ESC</p>
</noscript>
</figure>
HTML / WordPress (standard attributes, srcdoc lazy loading)
<figure class="video-embed" style="margin: 2.5rem 0; text-align: center;">
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; border-radius: 12px;">
<iframe
srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href='https://www.youtube.com/embed/VIDEO_ID?autoplay=1'><img src='https://img.youtube.com/vi/VIDEO_ID/hqdefault.jpg' alt='VIDEO_TITLE_ESC'><span>►</span></a>"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none;"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
sandbox="allow-scripts allow-same-origin allow-presentation"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen
title="VIDEO_TITLE_ESC"
aria-label="YouTube video: VIDEO_TITLE_ESC">
</iframe>
</div>
<noscript>
<p><strong>Video:</strong> <a href="https://www.youtube.com/watch?v=VIDEO_ID">VIDEO_TITLE_ESC</a> by CHANNEL_NAME_ESC. DESCRIPTION_EXCERPT_ESC</p>
</noscript>
</figure>
Standard Markdown (thumbnail link fallback)
[](https://www.youtube.com/watch?v=VIDEO_ID)
*Video: [VIDEO_TITLE](https://www.youtube.com/watch?v=VIDEO_ID) by CHANNEL_NAME*
Hugo
Use the built-in shortcode (do not use raw HTML embeds):
{{</* youtube VIDEO_ID */>}}
Next.js Config Note
For MDX projects using YouTube thumbnails, add to next.config.ts remotePatterns:
{ protocol: 'https', hostname: 'img.youtube.com' }
VideoObject JSON-LD Schema
Add a VideoObject to the page @graph for each embedded video. Use the stable
@id pattern with a video index suffix.
{
"@type": "VideoObject",
"@id": "{siteUrl}/blog/{slug}#video-{index}",
"name": "Video title",
"description": "Video description excerpt (first 200 chars)",
"thumbnailUrl": "https://img.youtube.com/vi/{videoId}/hqdefault.jpg",
"uploadDate": "YYYY-MM-DDTHH:MM:SSZ",
"contentUrl": "https://www.youtube.com/watch?v={videoId}",
"embedUrl": "https://www.youtube.com/embed/{videoId}",
"duration": "PT{M}M{S}S",
"interactionStatistic": {
"@type": "InteractionCounter",
"interactionType": { "@type": "WatchAction" },
"userInteractionCount": 0
}
}
Replace {index} with 1, 2, or 3 matching embed order. Replace
userInteractionCount with the numeric view count when available. Include
duration in ISO 8601 format (e.g., PT12M30S for 12 minutes 30 seconds).
Noscript Fallback for AI Crawlers
Standard crawlers such as GPTBot, PerplexityBot, and ClaudeBot should be assumed
not to execute JavaScript, so YouTube iframes may be invisible to them. The <noscript> block
provides a text fallback containing:
- Video title as anchor text linking to YouTube
- Channel name for source attribution
- Description excerpt for topical context
This ensures AI systems can discover and reference the video content even without rendering the embed. Every video embed must include a noscript fallback.
Graceful Degradation
| Scenario | Behavior |
|---|---|
| No GOOGLE_AI_API_KEY available | Use WebSearch site:youtube.com [topic] [year] to find videos |
| No suitable videos found | Skip silently, continue blog generation without video |
| API rate limit exceeded | Use cached/previously found videos, or skip |
| Video removed after embedding | Noscript text provides graceful fallback with title and link |
| Embed blocked by privacy settings | srcdoc pattern shows thumbnail placeholder until clicked |
| Reader has JavaScript disabled | Noscript block renders video title, channel, and description |
| 1 | # YouTube Video Embed Reference |
| 2 | |
| 3 | ## Why YouTube Embeds Matter |
| 4 | |
| 5 | Video can improve engagement and extraction when it is relevant, current, and |
| 6 | high quality. Treat vendor correlation studies as directional, not as ranking |
| 7 | requirements. Key data points: |
| 8 | |
| 9 | **0.737 correlation** with AI visibility, the strongest single signal (Ahrefs 75K-brand study) |
| 10 | Video citations in AI Overviews up **414%** year-over-year (NP Digital Q1 2025, 10K+ AIO analysis) |
| 11 | How-to video citations up **651%**, visual demo citations up **592%** (NP Digital) |
| 12 | YouTube is cited **200x more** than any other video platform by AI systems |
| 13 | |
| 14 | Strongly prefer relevant YouTube embeds when a suitable video exists. Skip video |
| 15 | when available videos are stale, low quality, off-topic, or would distract from |
| 16 | the article. |
| 17 | |
| 18 | |
| 19 | |
| 20 | ## Video Quality Criteria |
| 21 | |
| 22 | ### Minimum Standards |
| 23 | |
| 24 | | Criterion | Minimum | Preferred | |
| 25 | |-----------|---------|-----------| |
| 26 | | Views | >1,000 | >10,000 | |
| 27 | | Like ratio | >90% | >95% | |
| 28 | | Recency | <3 years | <18 months | |
| 29 | | Channel subscribers | >1,000 | >10,000 | |
| 30 | | Duration | >3 minutes | 5-15 minutes | |
| 31 | | Captions | Present | Accurate/manual | |
| 32 | | Relevance | Title keyword match | Title + description match | |
| 33 | |
| 34 | ### Quality Scoring Formula (0-100) |
| 35 | |
| 36 | | Factor | Weight | Scoring Method | |
| 37 | |--------|--------|---------------| |
| 38 | | Relevance (title/description keyword match) | 35 pts | Exact keyword in title = 35, partial = 20, description only = 10 | |
| 39 | | View count (log scale) | 20 pts | log10(views) / log10(10M) * 20, capped at 20 | |
| 40 | | Recency (months since publish) | 20 pts | max(0, 20 - (months_old * 0.8)) | |
| 41 | | Channel authority (subscribers, log scale) | 15 pts | log10(subs) / log10(1M) * 15, capped at 15 | |
| 42 | | Engagement (like ratio) | 10 pts | (like_ratio - 0.80) / 0.20 * 10, capped at 10 | |
| 43 | |
| 44 | **Minimum score threshold: 50/100.** Videos scoring below 50 should be skipped. |
| 45 | |
| 46 | |
| 47 | |
| 48 | ## Embed Placement Strategy |
| 49 | |
| 50 | | Position | Video Purpose | When | |
| 51 | |----------|--------------|------| |
| 52 | | After introduction (before first H2 body) | Overview / explainer | Always place 1st video here | |
| 53 | | Mid-article (after 2nd or 3rd H2) | Tutorial / demo / how-to | If video shows a process | |
| 54 | | Before FAQ or conclusion | Summary or expert opinion | Optional 3rd video | |
| 55 | |
| 56 | ### Placement Rules |
| 57 | |
| 58 | **2-3 videos per post** (never more than 3) |
| 59 | Minimum **500 words** between video embeds |
| 60 | Never place a video immediately before or after a chart |
| 61 | Videos **complement** text; they never replace written content |
| 62 | |
| 63 | |
| 64 | |
| 65 | ## Embed Code Patterns |
| 66 | |
| 67 | Before rendering any embed, validate `VIDEO_ID` against YouTube's ID pattern and |
| 68 | escape title, channel, and description fields with `html.escape(value, quote=True)`. |
| 69 | Reject untrusted `javascript:`, `data:`, and `file:` URLs. |
| 70 | |
| 71 | ### MDX / Next.js (camelCase, srcDoc lazy loading) |
| 72 | |
| 73 | |
| 74 | <figure className="video-embed" style={{margin: '2.5rem 0', textAlign: 'center'}}> |
| 75 | <div style={{position: 'relative', paddingBottom: '56.25%', height: 0, overflow: 'hidden', maxWidth: '100%', borderRadius: '12px'}}> |
| 76 | <iframe |
| 77 | srcDoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href='https://www.youtube.com/embed/VIDEO_ID?autoplay=1'><img src='https://img.youtube.com/vi/VIDEO_ID/hqdefault.jpg' alt='VIDEO_TITLE_ESC'><span>►</span></a>" |
| 78 | style={{position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', border: 'none'}} |
| 79 | loading="lazy" |
| 80 | allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" |
| 81 | sandbox="allow-scripts allow-same-origin allow-presentation" |
| 82 | referrerPolicy="strict-origin-when-cross-origin" |
| 83 | allowFullScreen |
| 84 | title="VIDEO_TITLE_ESC" |
| 85 | aria-label="YouTube video: VIDEO_TITLE_ESC" |
| 86 | /> |
| 87 | </div> |
| 88 | <noscript> |
| 89 | <p><strong>Video:</strong> <a href="https://www.youtube.com/watch?v=VIDEO_ID">VIDEO_TITLE_ESC</a> by CHANNEL_NAME_ESC. DESCRIPTION_EXCERPT_ESC</p> |
| 90 | </noscript> |
| 91 | </figure> |
| 92 | |
| 93 | |
| 94 | ### HTML / WordPress (standard attributes, srcdoc lazy loading) |
| 95 | |
| 96 | |
| 97 | <figure class="video-embed" style="margin: 2.5rem 0; text-align: center;"> |
| 98 | <div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; border-radius: 12px;"> |
| 99 | <iframe |
| 100 | srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href='https://www.youtube.com/embed/VIDEO_ID?autoplay=1'><img src='https://img.youtube.com/vi/VIDEO_ID/hqdefault.jpg' alt='VIDEO_TITLE_ESC'><span>►</span></a>" |
| 101 | style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none;" |
| 102 | loading="lazy" |
| 103 | allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" |
| 104 | sandbox="allow-scripts allow-same-origin allow-presentation" |
| 105 | referrerpolicy="strict-origin-when-cross-origin" |
| 106 | allowfullscreen |
| 107 | title="VIDEO_TITLE_ESC" |
| 108 | aria-label="YouTube video: VIDEO_TITLE_ESC"> |
| 109 | </iframe> |
| 110 | </div> |
| 111 | <noscript> |
| 112 | <p><strong>Video:</strong> <a href="https://www.youtube.com/watch?v=VIDEO_ID">VIDEO_TITLE_ESC</a> by CHANNEL_NAME_ESC. DESCRIPTION_EXCERPT_ESC</p> |
| 113 | </noscript> |
| 114 | </figure> |
| 115 | |
| 116 | |
| 117 | ### Standard Markdown (thumbnail link fallback) |
| 118 | |
| 119 | |
| 120 | [](https://www.youtube.com/watch?v=VIDEO_ID) |
| 121 | *Video: [VIDEO_TITLE](https://www.youtube.com/watch?v=VIDEO_ID) by CHANNEL_NAME* |
| 122 | |
| 123 | |
| 124 | ### Hugo |
| 125 | |
| 126 | Use the built-in shortcode (do not use raw HTML embeds): |
| 127 | |
| 128 | |
| 129 | {{</* youtube VIDEO_ID */>}} |
| 130 | |
| 131 | |
| 132 | ### Next.js Config Note |
| 133 | |
| 134 | For MDX projects using YouTube thumbnails, add to `next.config.ts` remotePatterns: |
| 135 | |
| 136 | |
| 137 | { protocol: 'https', hostname: 'img.youtube.com' } |
| 138 | |
| 139 | |
| 140 | |
| 141 | |
| 142 | ## VideoObject JSON-LD Schema |
| 143 | |
| 144 | Add a VideoObject to the page `@graph` for each embedded video. Use the stable |
| 145 | `@id` pattern with a video index suffix. |
| 146 | |
| 147 | |
| 148 | { |
| 149 | "@type": "VideoObject", |
| 150 | "@id": "{siteUrl}/blog/{slug}#video-{index}", |
| 151 | "name": "Video title", |
| 152 | "description": "Video description excerpt (first 200 chars)", |
| 153 | "thumbnailUrl": "https://img.youtube.com/vi/{videoId}/hqdefault.jpg", |
| 154 | "uploadDate": "YYYY-MM-DDTHH:MM:SSZ", |
| 155 | "contentUrl": "https://www.youtube.com/watch?v={videoId}", |
| 156 | "embedUrl": "https://www.youtube.com/embed/{videoId}", |
| 157 | "duration": "PT{M}M{S}S", |
| 158 | "interactionStatistic": { |
| 159 | "@type": "InteractionCounter", |
| 160 | "interactionType": { "@type": "WatchAction" }, |
| 161 | "userInteractionCount": 0 |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | |
| 166 | Replace `{index}` with 1, 2, or 3 matching embed order. Replace |
| 167 | `userInteractionCount` with the numeric view count when available. Include |
| 168 | `duration` in ISO 8601 format (e.g., `PT12M30S` for 12 minutes 30 seconds). |
| 169 | |
| 170 | |
| 171 | |
| 172 | ## Noscript Fallback for AI Crawlers |
| 173 | |
| 174 | Standard crawlers such as GPTBot, PerplexityBot, and ClaudeBot should be assumed |
| 175 | not to execute JavaScript, so YouTube iframes may be invisible to them. The `<noscript>` block |
| 176 | provides a text fallback containing: |
| 177 | |
| 178 | Video title as anchor text linking to YouTube |
| 179 | Channel name for source attribution |
| 180 | Description excerpt for topical context |
| 181 | |
| 182 | This ensures AI systems can discover and reference the video content even without |
| 183 | rendering the embed. Every video embed must include a noscript fallback. |
| 184 | |
| 185 | |
| 186 | |
| 187 | ## Graceful Degradation |
| 188 | |
| 189 | | Scenario | Behavior | |
| 190 | |----------|----------| |
| 191 | | No GOOGLE_AI_API_KEY available | Use WebSearch `site:youtube.com [topic] [year]` to find videos | |
| 192 | | No suitable videos found | Skip silently, continue blog generation without video | |
| 193 | | API rate limit exceeded | Use cached/previously found videos, or skip | |
| 194 | | Video removed after embedding | Noscript text provides graceful fallback with title and link | |
| 195 | | Embed blocked by privacy settings | srcdoc pattern shows thumbnail placeholder until clicked | |
| 196 | | Reader has JavaScript disabled | Noscript block renders video title, channel, and description | |
| 197 |
Discussion
Browse more free Claude skills.