DC Script Worker Proxy
Offload third-party scripts (GTM, Pixel, HubSpot…) to a Web Worker via Partytown + consent-aware loading + viewport/pagination prefetching for WooCommerce. Fully vendored — no npm required.
Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/dc-plugins/dc-script-worker-prefetcher/archive/refs/heads/main.zipOffload third-party scripts to a Web Worker via Partytown + consent-aware loading.
Offload third-party scripts (GTM, Pixel, HubSpot…) to a Web Worker via Partytown + consent-aware loading. Fully vendored — no npm required.
What it does
- Partytown Web Worker execution — Partytown moves third-party scripts into a Web Worker, off the main thread. Unlike
async/defer(which still block the main thread), Partytown executes scripts entirely off-thread. No layout jank, no TBT impact. Tested with: Google Tag Manager, Facebook Pixel, HubSpot, Intercom, Klaviyo, TikTok Pixel, Mixpanel (full list).
Note: Partytown is in beta. Review the trade-offs before using in production.
- Google Consent Mode v2 (GCM v2) — GCM v2-aware services (GTM, GA, Hotjar, Clarity, LinkedIn, TikTok) always run in the worker and self-restrict based on consent state. Meta Pixel uses its own Limited Data Use (LDU) toggle. Other services are blocked until consent is granted via the WP Consent API.
Consent architecture
The plugin uses a per-service consent gate so that each script class is handled by the most appropriate mechanism:
| Script class | Condition | Output type |
|---|---|---|
| GCM v2-aware service | GCM v2 enabled | text/partytown (always — service self-restricts) |
| Meta Pixel | Meta LDU enabled | text/partytown (always — fbq LDU stub injected) |
| Any other service | Consent Gate ON + wp_has_consent($category) true |
text/partytown |
| Any other service | Consent Gate ON + no consent | text/plain (browser blocked) |
| Any other service | Consent Gate OFF (default) | text/partytown (unconditional) |
GCM v2-aware services
These services implement the Google Consent Mode v2 API and adjust their own data collection when consent is denied. The plugin always loads them into the Partytown worker and lets them handle consent internally:
googletagmanager.com · google-analytics.com · static.hotjar.com · script.hotjar.com · clarity.ms · snap.licdn.com (LinkedIn) · analytics.tiktok.com
Developers can extend this list via the dc_swp_gcm_v2_aware_services filter.
Consent Gate — WP Consent API
The optional Consent Gate delegates consent decisions to the WP Consent API standard. When enabled:
- Scripts are output as
type="text/plain"with adata-wp-consent-categoryattribute until the visitor grants consent for that category. - A consent-change listener (
consent-gate.js) dynamically unblocks scripts when consent is granted, swappingtext/plaintotext/partytown. - Each inline script block has its own configurable consent category (marketing, statistics, statistics-anonymous, functional, preferences).
- The Script List default category is configurable in the admin settings.
- Any CMP that integrates with the WP Consent API is automatically supported — no per-CMP cookie reading code is required.
Known limitations
Full-page caching + Meta Pixel consent
The fbq("consent","revoke"/"grant") and LDU stubs are injected by PHP at request time. If a full-page cache plugin (WP Rocket, Nginx FastCGI, static HTML) serves a cached page without invoking PHP, the stub is baked in with the consent state of whoever filled the cache — not the current visitor's. Use per-visitor cache keys, fragment caching, or disable full-page caching for logged-out visitors.
Meta Pixel with Gate OFF and LDU OFF
If both the Meta LDU toggle and the Consent Gate are disabled, Meta Pixel fires with no fbq("consent",...) call. Meta receives data without any explicit consent declaration from this plugin. Enable Meta LDU, the Consent Gate, or both to emit meaningful consent signals.
How Partytown works
- Scripts matching your configured patterns are output with
type="text/partytown"— this tells the browser not to execute them on the main thread. - A Web Worker receives and executes those scripts entirely off the main thread.
- JavaScript Proxies replicate main-thread APIs (DOM reads/writes) synchronously inside the worker — third-party scripts run exactly as coded, without modification.
- Communication between the web worker and main thread uses one of two bridges:
- Atomics bridge (
crossOriginIsolatedactive) — worker writes a request into aSharedArrayBufferslot and callsAtomics.wait()to block; main thread reads the slot, writes the response, and callsAtomics.notify()to wake the worker. No service worker involved. Roughly 10× faster round-trips. Enabled via the COI Headers setting. - Service Worker bridge (fallback when COI is unavailable) — worker makes a synchronous XHR to a synthetic URL; a registered service worker intercepts it, relays the message to the main thread, and returns the response as the XHR body.
- Atomics bridge (
Architecture
Page request (PHP)
└─ dc_swp_partytown_script_attrs() ← per-service consent gate
├─ GCM v2-aware service + GCM v2 enabled → type="text/partytown" (service self-restricts)
├─ Meta Pixel + Meta LDU enabled → type="text/partytown" (fbq LDU stub active)
├─ Other service + marketing consent → type="text/partytown"
└─ Other service + no consent → type="text/plain" (browser blocked)
Key features
- No npm / no build step — Partytown lib files are vendored in
assets/partytown/ - Auto-detect — one-click scan in admin discovers external scripts on your homepage
- Pattern-based — enter one URL pattern per line; full URLs and partial patterns both work
- Consent Gate (WP Consent API) — optional toggle blocks scripts as
text/plainuntil the visitor grants consent via any CMP that integrates with the WP Consent API; per-script consent category support - GCM v2 per-service gate — GCM v2-aware services always run in the worker and self-restrict; Meta Pixel uses LDU
- Consent Architecture panel — collapsible admin panel shows GCM v2-aware services and Meta LDU badges (shields.io SVGs + offline CSS fallback)
- Bot-safe — bots receive no Partytown JS (clean HTML for crawlers)
- Cart/checkout safe — Partytown uses the Service Worker bridge on cart, checkout, and account pages (Atomics bridge auto-disabled); analytics scripts still fire without breaking payment gateways
- Bilingual admin — English default, Danish auto-detected from WP locale
- Weekly auto-updates — GitHub Actions workflow opens a PR when a new Partytown release is detected
Installation
- Upload the
dc-script-worker-prefetcherfolder to/wp-content/plugins/. - Activate from the Plugins screen.
- Go to SW Prefetch in the admin menu.
- Add URL patterns for any third-party scripts you want to offload (e.g.
analytics.ahrefs.comor the full GTM URL). Use the Auto-Detect button to scan your homepage. - Save.
The window.partytown.forward array is pre-configured for all officially tested services: dataLayer.push (GTM), fbq (Facebook Pixel), _hsq.push (HubSpot), Intercom, _learnq.push (Klaviyo), ttq.track/ttq.page/ttq.load (TikTok Pixel), mixpanel.track (Mixpanel), FS.identify/FS.event (FullStory). See partytown.qwik.dev/common-services for details.
Updating the vendored Partytown library
Automatic: the update-partytown.yml workflow runs every Monday at 08:00 UTC.
Manual:
# Latest release
bash scripts/update-partytown.sh
# Pin a specific version
bash scripts/update-partytown.sh 0.11.2
Then commit assets/partytown/ and package.json.
Repository structure
dc-script-worker-prefetcher.php — Main plugin file
admin.php — Admin settings page (EN/DA)
uninstall.php — Cleanup on deletion
assets/partytown/ — Vendored Partytown lib (do NOT hand-edit)
scripts/ — update-partytown.sh
.github/workflows/ — deploy.yml, update-partytown.yml
package.json — Tracks vendored Partytown version
languages/ — .pot translation template
External Services
This plugin runs third-party scripts off the main thread using the vendored Partytown library. It only connects to services you explicitly configure.
Partytown library
The Partytown JavaScript library is fully vendored inside the plugin (assets/partytown/). No files are downloaded from any CDN at runtime; the library is loaded from your own server.
CORS proxy (server-side script relay)
Some third-party CDNs do not send CORS headers, which prevents Partytown's sandbox from fetching their scripts directly from the browser. The plugin provides a /~partytown-proxy endpoint: WordPress makes a server-side HTTP GET request to the CDN and re-serves the script to the browser.
- What is sent: the script file request only — no visitor personal data.
- When: only when Partytown cannot fetch a script directly, and only for hostnames the administrator has added to the Partytown Script List.
- Allowlist-only: the proxy strictly rejects any hostname not configured by the administrator.
Third-party analytics and marketing scripts (administrator-configured)
When the administrator adds a service's URL pattern to the Partytown Script List, that service's script loads inside a Web Worker (via Partytown) for visitors who have granted marketing consent. The visitor's browser (or the CORS proxy) contacts the service's CDN, and the service may receive visitor data per its own terms.
Scripts are only loaded when:
- The administrator has added the service's URL pattern to the Partytown Script List or Inline Script Blocks.
- If the Consent Gate is enabled, the visitor has granted consent for the script's category via the WP Consent API. Without consent, scripts are blocked (
type="text/plain"). If the Consent Gate is disabled (default), scripts load unconditionally.
The plugin ships pre-configured forwarding for these officially tested services:
| Service | Provider | Data sent | Privacy | Terms |
|---|---|---|---|---|
| Google Tag Manager / GA4 | Google LLC | Page URL, visitor interactions | Privacy | Terms |
| Meta (Facebook) Pixel | Meta Platforms, Inc. | Page URL, events, hashed identifiers | Privacy | Terms |
| HubSpot Analytics | HubSpot, Inc. | Page views, form interactions | Privacy | Terms |
| Intercom | Intercom R&D Unlimited Company | Visitor identity, page views, events | Privacy | Terms |
| Klaviyo | Klaviyo, Inc. | Page views, cart/checkout events, email | Privacy | Terms |
| TikTok Pixel | TikTok Inc. / ByteDance Ltd. | Page views, events, hashed identifiers | Privacy | Terms |
| Mixpanel | Mixpanel, Inc. | Page views, events, anonymous visitor ID | Privacy | Terms |
| FullStory | FullStory, Inc. | Session replay, events, visitor identity | Privacy | Terms |
The administrator may configure additional services via the Partytown Script List. Refer to each service's own privacy policy and terms of service for details on collected data.
Changelog
3.1.0
- Fix: Inline Script Blocks rebuilt as Script Center — JS is sanitised with
sanitize_text_field()at save time and always rendered astype="text/plain"(consent-gated); no arbitrary script execution path remains. - Fix: Removed PayPal 1×1 tracking pixel and
paypalobjects.comdonate image; replaced with a plain text button. - Fix: Removed all
img.shields.iorequests from admin UI; Consent Architecture panel now uses pure-CSS badges. - Fix: Added FullStory to
readme.txtExternal Services section. - Fix: All external `