| U65 | **8** remote player SDK URLs — YouTube, Vimeo, SoundCloud, Dailymotion, Mixcloud, **Cloudflare Stream `sdk.latest.js` (floating, UD-6)**, Spotify, Twitch. **Dailymotion is the only parameterized one, and the only one still built in PHP**: `https://geo.dailymotion.com/libs/player/<PLAYER_ID>.js` when the site configured a player ID, else the ID-less `https://geo.dailymotion.com/libs/player.js`. Its predecessor `api.dmcdn.net/all.js` was sunset for player integration on **2026-02-03** and is the textbook UD-11 case — the file still returns 200 and only `console.warn`s, so nothing on our side ever observed that every Dailymotion event had stopped firing. Three Dailymotion claims, each weaker than a plain "does the URL resolve": (1) the **ID-less** `libs/player.js` still returns a working library (`"player":{"id":"default",…,"status":"ok"}`) — this is **our own discovery, not a documented entry point**, so it carries a weaker promise than the per-player URL and is what keeps the feature usable without a Dailymotion Studio account; (2) the file **must not be self-hosted or cached** — its own header says *"generated dynamically, do not host it yourself. Statically hosting or caching this file will break your integration"*, recorded here because "self-host the SDK for performance" is exactly the optimization a future contributor reaches for; (3) `createPlayer`'s `player` option still overrides the loaded library's configuration, which is what lets a `/player/<pid>.html` embed keep its own player on a site that configured none. YouTube's `//www.youtube.com/iframe_api` is **protocol-relative and was previously unregistered** — it was the one SDK the tracker already injected itself, so it never appeared in the PHP enqueue list this row used to describe (UD-1: a coupling with no row is invisible, not unverified). **Mixcloud has split its loader from its app** — the URL we load, `https://widget.mixcloud.com/media/js/widgetApi.js`, is still the loader and still the API surface we bind to, while the player *application* now ships from `player-widget.mixcloud.com` as a Vite build (`/assets/index-<hash>.js`). The two hosts can retire independently, so a 200 on the app host says nothing about ours, and the plausible-looking `player-widget.mixcloud.com/widget/js/api.js` is a **404** — do not "modernize" the URL to a host that does not serve it | `js/frontend/gtm4wp-*.js` — the 4th argument to `gtm4wpObserveMedia()` (a bare URL, or `{ src, subscribe }` for YouTube/Spotify, whose SDKs signal readiness through a global callback). **Moved here from `MediaEventsModule.php` when the SDKs stopped being enqueued for every page**: PHP cannot see whether the rendered page has an embed, so all 8 are now fetched by the tracker only after its DOM scan finds one. ⚠️ **Three of the eight are two-hop loaders, not the API** — measured 2026-08-07: YouTube's `iframe_api` is ~1.2 KB that only assigns `YT={loading:0,loaded:0}` and injects `www-widgetapi-script`; Spotify's `/embed/iframe-api/v1` is ~1.1 KB that does **not** itself define `onSpotifyIframeApiReady` or `createController`; Mixcloud's `widgetApi.js` is the loader for an app now shipped from `player-widget.mixcloud.com`. For these three the URL we pin and the code that actually defines the global are **different, independently retireable artifacts**, and the second hop is unversioned and invisible to us — so a 200 on the loader is evidence about the loader and nothing else. Both readiness gates that survive this are the ones testing the *member* (`YT.Player`, the fired callback), never the bare global. **Dailymotion is the half-exception**: `MediaEventsModule::enqueue_scripts()` still *builds* its URL (only PHP has the stored player ID, and only PHP can `rawurlencode()` it where it enters the path) and publishes it as `gtm4wp_dailymotion_config.sdk` via `wp_add_inline_script(..., 'before')` — the tracker fetches it, never assembles it, so the URL still has exactly one definition | reachability + API shape. Claim to re-verify per SDK: **the URL still returns 2xx JavaScript and still assigns the global U66 names** — measured with a request, never inferred from the absence of complaints (UD-11: nothing on our side observes a dead SDK; the tracker simply never wires). Pinned from our side by a per-tracker `SDK loading` describe in `js/frontend/test/<provider>-tracker.test.js`, which asserts the exact URL is requested when an embed is present and that **nothing** is requested when it is not. ⚠️ **Reachability is the weaker half of this row and cannot be the whole check** — see the Watch column: Dailymotion's sunset SDK kept returning 200 for six months after it stopped working | **Vendor deprecation / changelog channels — check these, not just the CDN.** Verified live 2026-08-07: YouTube → the **Revision History** section of `developers.google.com/youtube/iframe_api_reference` (last entry 2025-07-09; already lists `getPlaybackQuality`/`setPlaybackQuality` as no-ops); Vimeo → `github.com/vimeo/player.js/releases` (**the strongest channel here — the only SDK that ships a real version number**, so it can be diffed rather than sniffed); Cloudflare Stream → `developers.cloudflare.com/changelog/` filtered to Stream, RSS at `/changelog/rss/index.xml`; Twitch → `dev.twitch.tv/docs/change-log`; SoundCloud → `github.com/soundcloud/Widget-JS-API` + `developers.soundcloud.com/docs/api/html5-widget` (**weak**: repo is unarchived but near-dormant, README carries no version and no notice, so absence of news is not news); Spotify → `developer.spotify.com/community/news/` (**candidate, not yet verified**) — note the `/v1` in our URL is itself the signal, a `/v2` appearing is the drift event; Mixcloud → **no formal channel exists**, which is why its loader/app split had to be discovered by fetching. Dailymotion → **`reference/migration-guide-new-embed-endpoint` and the `dailymotion/dailymotion-sdk-js` README, NOT `reference/deprecations`**: that page read *"We don't have ongoing deprecation for the moment"* throughout the entire player sunset and still does, so watching the page named "deprecations" would have caught nothing. The lesson generalises — a vendor's *migration guide* carries dated milestones its deprecation page may never mention | silent-missing | quarterly | [x] 2026-08-07 **all 8 fetched, all current, none deprecated.** YouTube `iframe_api` → 200, ~1.2 KB, assigns `YT={loading:0,loaded:0}` and injects `www-widgetapi-script`; Vimeo → 200, banner `@vimeo/player v2.30.4 \| (c) 2026`, assigns `Vimeo.Player` — **matches the latest GitHub release (v2.30.4, 29 Apr), so we are exactly current**; SoundCloud → 200, ~3.8 KB, `window.SC=window.SC\|\|{},window.SC.Widget=i`; Dailymotion → the new `geo.dailymotion.com/libs/player.js`, 200, `"player":{"id":"default",…,"status":"ok"}`; Mixcloud → 200, 194 597 bytes (verified 2026-08-05, unchanged); Cloudflare Stream → 200, ~20 KB, `window.Stream=function(r)`, internal `1.6.7`, and the docs still name this exact host+path; Spotify → 200, ~1.1 KB **loader only**; Twitch → 200, ~19.3 KB UMD assigning `Twitch` with `Embed` and `Player`, changelog current to 2026-07-31 with nothing about embeds. **No vendor body contained "deprecat", "sunset", "no longer supported" or "legacy"** |
0 commit comments