Hold YouTube videos and other iframes until visitors accept their category in TermsFeed Free Cookie Consent
Replace each embedded iframe with a placeholder that keeps its address in a data- attribute, then add a Cookie Consent tagged script that puts the iframe back. The iframe returns the moment the visitor accepts the category of the placeholder, with no page reload, and loads once it is near the visible part of the page. Visitors who decline see the placeholder, with a button that opens the Preferences Center.
Cookie Consent holds only <script> elements tagged with type="text/plain" and data-cookie-consent. It does not block an <iframe>, an <img>, or a pixel. An embed pasted as YouTube provides it loads on page load and sets its cookies before the visitor answers.
Choose the Cookie Consent category for each embed
Give each embed the category that matches what the service does with visitor data. A video player, a map, or a booking widget the visitor uses on purpose fits functionality, the category the YouTube and Calendly recipes use. A social media post that tracks visitors for advertising fits targeting.
The category decides which switch in the Preferences Center releases the embed. Find the category for YouTube, Calendly, and the other tools with a recipe in Vendor Recipes for Free Cookie Consent.
The setup takes about 15 minutes. You need access to the HTML of the page that holds the embed and to the run() options of your Cookie Consent block.
Step 1: Replace the embed with a placeholder
Remove the <iframe> and put a <div> in its place that holds the iframe address in data-cc-src and the category in data-cc-category. The browser loads nothing from an address kept in a data- attribute, so no request reaches the service before consent.
Replace VIDEO_ID in this YouTube placeholder with the ID of your video, and copy the title, width, height, and allow values of your original iframe into the matching data-cc- attributes.
<div class="cc-embed"
data-cc-category="functionality"
data-cc-src="https://www.youtube-nocookie.com/embed/VIDEO_ID"
data-cc-title="Product tour video"
data-cc-width="560"
data-cc-height="315"
data-cc-allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share">
<p>This video is hosted on YouTube, which receives your IP address once it loads. Accept functionality cookies to watch it here.</p>
<button type="button" class="open-cookie-preferences">Change my cookie preferences</button>
</div>
The privacy-enhanced address youtube-nocookie.com still loads content from Google, so keep the placeholder for that address too, until the visitor accepts. Read why privacy-enhanced mode still needs consent in Block YouTube Embeds Until Consent.
Step 2: Add a tagged script that loads the embed
Add one script tagged with the same category as the placeholder, which finds every placeholder of that category and replaces it with the iframe. Cookie Consent runs the script when the visitor accepts the category and on every later page load of a visitor who accepted, but never for a visitor who declined it. In express mode, before the answer, it runs the script only when page_load_consent_levels lists the category.
Paste this functionality script anywhere in the page HTML, because the generator code starts run() on DOMContentLoaded, after the browser has parsed every tagged script.
<script type="text/plain" data-cookie-consent="functionality">
(function () {
var placeholders = document.querySelectorAll('.cc-embed[data-cc-category="functionality"]');
for (var i = 0; i < placeholders.length; i++) {
var placeholder = placeholders[i];
var iframe = document.createElement('iframe');
iframe.src = placeholder.getAttribute('data-cc-src');
iframe.title = placeholder.getAttribute('data-cc-title') || '';
iframe.width = placeholder.getAttribute('data-cc-width') || '560';
iframe.height = placeholder.getAttribute('data-cc-height') || '315';
iframe.setAttribute('allow', placeholder.getAttribute('data-cc-allow') || '');
iframe.setAttribute('allowfullscreen', '');
iframe.setAttribute('loading', 'lazy');
iframe.setAttribute('frameborder', '0');
placeholder.parentNode.replaceChild(iframe, placeholder);
}
})();
</script>
Copy the script once per category your embeds use, and change functionality in both places, the data-cookie-consent attribute and the selector. A targeting copy loads the social posts marked data-cc-category="targeting".
Cookie Consent runs the script once per page, so it replaces only the placeholders already in the page. A placeholder your code adds later, such as on a route change in a single-page app, stays in place. Run the same placeholder swap from your route change code once the category is accepted, with the consent checks in Single-Page Apps and Frameworks.
Step 3: Let visitors open the Preferences Center from the placeholder
Add the placeholder button to open_preferences_center_selector, so a click opens the Preferences Center where the visitor turns the category on. Cookie Consent checks the selector on every click, so buttons inside placeholders work wherever they sit in the page.
The default selector is #open_preferences_center, the footer link the TermsFeed generator writes. Add .open-cookie-preferences to the open_preferences_center_selector list already in your run() call. With no such option yet, add this list, which keeps that link and adds the placeholder buttons, next to the other options in your run() call.
"open_preferences_center_selector": "#open_preferences_center, .open-cookie-preferences",
The visitor turns on the category and clicks the "Save my preferences" button. Cookie Consent runs the tagged script at once, and the iframe replaces the placeholder with no reload. Read the other ways to open the Preferences Center in Add a Cookie Settings Link.
Step 4: Verify that the embed waits for consent
The checks assume express consent with page_load_consent_levels left out or at the generator value ["strictly-necessary"], and the "I decline" button shown. Publish the change and clear any page cache. Close every private window and open a new one before the check, so no earlier answer hides the consent banner. On a working page, no request reaches the embed host before you accept.
- Open Chrome DevTools, select the Network tab, type
youtubein the filter box, open the page with the YouTube example, and scroll to the placeholder. No request appears, and the placeholder shows its text and button. - Click the "Change my cookie preferences" button in the placeholder, select the "Functionality cookies" tab, set its switch to Active, and click the "Save my preferences" button. Requests to
youtube-nocookie.comappear, and the video replaces the placeholder. - Reload the page, scroll to the video, and confirm that it loads with no click, because the visitor accepted
functionality. The iframe loads lazily, so a player below the fold does not send a request until you scroll to it. - Close every private window and open a new one. Open DevTools, type
youtubein the Network filter, open the page, click the "I decline" button, and scroll to the placeholder. No request toyoutubeappears, and the placeholder stays on the page.
Style the placeholder so it holds the space of the embed
Give the placeholder the size of the embed, so the page does not jump when the iframe replaces it. The class names are yours, as long as the markup, the script selector, the open_preferences_center_selector list, and the stylesheet use the same ones.
Add this starting style for a 16:9 video placeholder to your site stylesheet.
.cc-embed {
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
max-width: 560px;
aspect-ratio: 16 / 9;
padding: 1.5rem;
background: #f2f2f2;
border: 1px solid #d9dde5;
border-radius: 8px;
text-align: center;
}
.cc-embed p {
margin: 0;
}
.cc-embed .open-cookie-preferences {
padding: 0.5rem 1rem;
cursor: pointer;
}
Write the placeholder text so it says who provides the content and which category releases it. A visitor who reads "Accept functionality cookies to watch it here" knows which switch to turn on.
Use the same pattern for other iframe embeds
The pattern of a placeholder and a tagged script works for any content that arrives as an <iframe>, such as another video player, a map, or an embedded form. Change the address in data-cc-src, the size, and the category, and add a copy of the script for each category that no script copy covers yet.
Some embeds load through a vendor <script>, such as the Calendly scheduler. Tag the vendor script itself with the category, and keep a fallback link in the markup for visitors who decline. A short tagged script removes the link on consent. Copy the markup and the category for the YouTube player and the Calendly scheduler from Block YouTube Embeds Until Consent and Block Calendly Until Consent.
Common mistakes with embedded content
An embed loads before consent when an iframe keeps its src attribute, or when something other than Cookie Consent loads the iframe, and never loads when its tagged script never runs. Check the page markup and your plugins for each of these mistakes.
- The iframe keeps its
src. The browser loads an iframe as soon as it has asrc, so the Network tab shows requests to the embed host before you answer. Search the page source for<iframeand look for asrcattribute on each match. Move the address todata-cc-srcon a<div>. - The iframe carries
type="text/plain". The iframe loads as usual, and the Network tab shows requests to the embed host before you answer. Search the page source for<iframeand look fortype="text/plain"on each match. Use the placeholder and the tagged script. - The category is not in
notice_banner_purposes_levels. The tagged script of an optional category left out of that option never runs, so the embed never loads. With"debug": true, the Console showsJavaScript script of the category "functionality" never runs. Add the category to the option, or use one that is in it. - Your own code adds the tagged script later. The placeholder stays after the visitor accepts, and the page source does not hold a tagged script. Keep the script in the HTML the server sends, so it exists when
run()starts. - A lazy-loading plugin rewrites the iframe. Some WordPress and page-speed plugins turn iframes into their own placeholders and load them on scroll, outside Cookie Consent. Requests to the embed host then appear in the Network tab as you scroll, before you answer. Exclude the page or the embed from the plugin.
A visitor who withdraws keeps the iframe until the next page load, and the cookies the service stored stay until they expire. Cookie Consent does not stop scripts that already ran or delete cookies set by the service. Reload the page after a change of choice with Reload the Page After Consent.