The one rule
Nothing third-party loads before the visitor clicks. Not a script, not an iframe, not a thumbnail, not a
preconnect.
That is the plugin’s entire product. A customization that breaks it has not customised the plugin, it has removed it. Concretely, in your own code:
- Don’t fetch a poster or favicon from the provider Posters must come from your own site. The supported route is the Set poster image control in the block inspector — the server rejects any poster URL that does not resolve to your own host. Since 1.0.0 that includes the uploads base, so a CDN-offloaded media library usually needs nothing: most CDN plugins filter the WordPress functions that report where your files live, and the offloaded host is read from those. Declare it under Detection → Additional own hosts if yours does not — a CDN that rewrites the finished page never reaches those functions.
- Don’t add
autoplayAnd don’t widenalloworsandboxpast what the original embed had. Autoplay is a WCAG 1.4.2 failure and is not what the visitor asked for. - Don’t write cookies or
localStoragebefore the click Not even to remember something. Pre-consent storage is the problem the plugin exists to remove. - Don’t put compliance claims in custom notes or button text It is a technical measure and makes no legal claims — yours shouldn’t either.
- Don’t emit a literal
<iframeNot inside placeholder markup. Gated content can be re-processed and a raw iframe would be re-detected. - Keep the server-rendered fallback link Someone with JavaScript off must still get a real link to the content.
The gate fails closed, which is your safety net: an unknown third-party iframe is caught by the generic rule even when your descriptor is wrong. A broken customization shows a generic panel — it never silently lets a tracker through.
Adding a provider
- Start on the settings screen Since 0.10.0 the Providers tab takes a host name directly: give it the embed host (and any script host), pick a kind so the button gets the right icon, and it gets the same notice, button text and privacy-policy controls as a built-in. No code, and nothing to break — unknown hosts are gated either way, a host a built-in already handles is refused with a notice, and your own providers are always gated.
- Drop to a descriptor only when you must Reach for code when you need what the settings screen cannot express: a path pattern, a privacy-preserving load target, query parameters merged at load time, or a fallback URL built from the embed’s own id. Providers are descriptor arrays, not classes — ten lines in
functions.phpis a complete one.
The descriptor keys, their defaults and a worked example are on the API reference.
Verify every change
wp calucon-embed-gate scan --format=json # every embed found, and whether it is gated
wp calucon-embed-gate providers --format=json # providers as the gate resolves themRun both. They are read-only and make no outbound request, so they are safe on a live site.
Every third-party row must read
status: gated. Anything else means “loads without consent, because a setting says so” — the API reference lists what each status means.Then confirm in a browser. This is the check that actually proves the claim: devtools → Network → filter out your own domain → reload. Before any click, the list must be empty.
Where to look things up
- API reference Every filter and action with its signature, firing point, return contract and a runnable example, plus the settings schema, the WP-CLI commands, the placeholder markup contract, the CSS custom properties and the front-end JavaScript surface.
- Plugin overview What it does and why.
- Live demo Every provider on one page, with nothing loading until you press a button.
- Source on GitHub Issues, and private security reporting. Any way to make a page contact a third party before the click counts as a vulnerability.
- WordPress.org Install, changelog, support forum.
docs/customizing.mdShipped inside the plugin — the same material as this page, and since 1.0.0 a section on caching, minification and CDN plugins that this page does not duplicate: a symptom → cause → fix table, and where each optimisation plugin keeps its exclusion list.
