Embed YouTube videos without tracking cookies
@slashclone/privacy-friendly-youtube-embed
Embed YouTube videos on your site without loading anything from Google until the visitor presses Play or allows videos. A click-to-play placeholder with a local poster swaps in the youtube-nocookie.com player, with a keyboard-friendly button, no layout shift, CSP entries, and a Playwright test that proves no YouTube request happens first. React and HTML templates. Not legal advice.
SkillDevOpsv0.1.1 (latest)
- Activity
- New: be the first to try it
- Installs
- 0 installs
- Likes
- 0 likes
- Clones
- 0 clones
- 1---
- 2name: privacy-friendly-youtube-embed
- 3description: "Embed YouTube videos in a web app without loading anything from Google until the visitor asks: a click-to-play placeholder with a local poster, the youtube-nocookie.com player after the click or after consent, CSP entries only when embeds exist, an accessible play button, 16:9 sizing with no layout shift, and a Playwright test that proves no YouTube request happens first. Reads consent from your existing consent layer. Engineering guidance, not legal advice. Use when adding a YouTube video to a page, when asked to \"embed this video\", for a GDPR-friendly or lazy-loaded YouTube embed, or when a privacy audit flags YouTube iframes, cookies, or thumbnails."
- 4---
- 6# Privacy-friendly YouTube embed
- 8Goal: a page with a video makes zero requests to YouTube or Google until the visitor presses Play or has allowed embedded videos. The page still looks finished, the button works by keyboard, and the layout does not jump. This is engineering guidance, not legal advice.
- 10## Where consent comes from
- 12This kit does not build a consent banner. It reads one. If the site has no consent layer yet, set one up first with `@slashclone/cookie-consent-banner`, which defines an "Embedded media" category and the CSP registry this kit plugs into. Then pass that category's state to the embed as `allowed`, and its "grant" function as `onAllowAll`.
- 14Pressing Play on one video is a clear, specific request to load that video. It loads that one player. It does not change the stored consent. "Always allow videos" is the only control here that changes consent, and only if you wire it.
- 16## Steps
- 181. **Find every embed.** Search the code for `youtube.com/embed`, `youtube-nocookie.com`, `youtu.be`, `ytimg.com`, `<iframe`, and any YouTube or "lite embed" package. Also check CMS content and Markdown, where editors paste iframes. List each one with its page.
- 192. **Pick the template.** React: copy `templates/YouTubeEmbed.tsx` into the components folder. Plain HTML: copy `templates/youtube-embed.js` and the styles from `templates/youtube-embed.html`. Both do the same thing: parse the link, show a placeholder, swap in the player on click or when consent is granted.
- 203. **Make a local poster.** Do not use `i.ytimg.com` thumbnails before consent. That is a request to Google that sends the visitor's IP address. Download the frame you want once, by hand, and serve it from your own origin. Or use a plain neutral background. Give it `alt=""`, since the title is already in text next to it.
- 214. **Fill in the placeholder.** Title is required: it is the iframe `title` later and the button's accessible name now. Add the duration if you know it. Say plainly that playing loads the video from YouTube, which may set cookies. Add a "Watch on YouTube" link: a plain link fetches nothing until clicked.
- 225. **Load the player only on demand.** Use `https://www.youtube-nocookie.com/embed/<id>`. On click, add `autoplay=1` so one press starts the video. When consent was granted earlier, render the iframe with `loading="lazy"` and no autoplay. Keep `referrerpolicy="strict-origin-when-cross-origin"`: the player needs your origin to play and this sends no path.
- 236. **Keep the box stable.** The wrapper uses `aspect-ratio: 16 / 9` and `width: 100%`. The placeholder and the iframe both fill it absolutely, so swapping one for the other moves nothing. Do not size the iframe with `width` and `height` attributes alone.
- 247. **Accessibility.**
- 25 - The play control is a real `<button type="button">` with the name "Play video: <title>". Not a `div` with a click handler.
- 26 - Keep a visible focus outline on the button and links.
- 27 - After the click, move focus to the iframe so keyboard users land in the player.
- 28 - Captions: pass `captions` (adds `cc_load_policy=1`) when the video has good captions. The video owner must upload them; auto-captions are often wrong. Link a transcript on your own site when you have one.
- 298. **Add the CSP entries only when used.** Use `templates/csp-youtube.ts` or add by hand: `frame-src https://www.youtube-nocookie.com`. Only add `img-src https://i.ytimg.com` if you show YouTube thumbnails after consent. If the site has no embeds, add nothing. With the consent banner kit, add the same host to the YouTube entry in its registry so the policy and the cookie table stay in step.
- 309. **Watch for hidden prefetches.** Speculation rules, link prefetch, or a framework's automatic prefetch can fetch the "Watch on YouTube" link. Exclude external links from them.
- 3110. **Test it.** Adapt `templates/youtube-embed.spec.ts` (Playwright) to a page with one embed, using the project's existing end-to-end runner. It checks: no request to any YouTube or Google host before the click, even after scrolling the video into view; Enter on the button loads the nocookie player with focus on it; the box keeps its height. Ask before adding a test runner the project does not already have. Then check once by hand in a fresh private window with the network panel open.
- 33## Rules
- 35- Never request anything from YouTube or Google before a click or consent. That includes thumbnails, the iframe API script, and preconnect hints.
- 36- Never use `www.youtube.com/embed` when `www.youtube-nocookie.com/embed` works. The nocookie player still sets storage once it plays, so it still needs a click or consent.
- 37- Never autoplay a video the visitor did not just ask for.
- 38- Never treat one Play click as consent for every video. Store consent only from an explicit "allow" control.
- 39- Never claim the site is compliant. Report what you checked and what still needs a lawyer.
- 40- If a request conflicts with these rules (for example "use the YouTube thumbnail, it looks better"), explain the tradeoff and ask before going ahead.
