Club integrations
The third-party services only this site uses, each wrapped in one package and off until its environment variable is set.
The integration seams
Six packages are this site's own (the template has none of them), each wrapping one third party so its SDK or script is loaded in exactly one place. What each integration gives fans, and its status, is in Integrations; this page is how they are built.
The shared shape
- One importer. The package is the only place the vendor's SDK, script or library is imported; a vendor change touches that package and nothing else.
- A server-safe root and a
./cliententry. The root holds settings, rules and links that server code can read; the client entry holds the provider, hooks or mount. - Off until configured. Each is declared in
apps/web/club.config.tsonly when its variable is set (the presence-gated blocks in Env markers), so CI,pnpm verifyand local development build without any of them, and an unconfigured integration draws nothing and downloads nothing.
The six packages
| Package | Vendor | Switched on by | Where it mounts |
|---|---|---|---|
@v4/wsc |
WSC Sports stories and clips (Blaze web SDK, pinned exactly) | NEXT_PUBLIC_WSC_API_KEY |
WscProvider in the locale layout; WscWidget in the WSC content block (wscWidget, club/0009) and the team and player pages' rails |
@v4/eltv |
EuroLeague TV (Deltatre Vesper SDK, pinned exactly) | NEXT_PUBLIC_VESPER_API_KEY; the player also needs NEXT_PUBLIC_ELTV_ACCESS_URL |
Not mounted yet — the Game Centre links out to ELTV (see The ELTV livestream) |
@v4/ecal |
ECAL "Add to calendar" widget | NEXT_PUBLIC_ECAL_API_KEY |
EcalProvider in the locale layout; the Games page's schedule picker (EcalSchedulePicker), per-competition displays in features.calendar.displays |
@v4/analytics |
Google Tag Manager and OneTrust | NEXT_PUBLIC_GTM_CONTAINER_ID, NEXT_PUBLIC_ONETRUST_DOMAIN_SCRIPT_ID |
The head scripts and AnalyticsProvider in the locale layout; PageAnalytics on every route |
@v4/cortex-sso |
Cortex (EuroLeague ID) over NextAuth | CORTEX_SSO_BASE_URL (its companions then required) |
app/api/auth/[...nextauth], auth/login/return, auth/logout; the header's session hook |
@v4/code-of-conduct |
— (email to ELB) | Always mounted; sending needs an email provider | /en/code-of-conduct and app/api/code-of-conduct/{games,reporter,report} |
Analytics and consent
No GA4 or gtag.js is loaded: every tag lives in
ELB's GTM container, and @v4/analytics is the only place the site pushes to
the dataLayer. OneTrust's groups map onto the tracking plan's four consent
categories, Consent Mode v2 is set before GTM loads, and without OneTrust
nothing is ever sent — every event waits for consent. Each route renders
PageAnalytics so its page_viewed says what the page is.
Sign-in
features.auth is an adapter seam, so Cortex's settings are read
by readCortexSsoSettings(process.env) rather than through env markers, and a
missing companion variable fails the build by name. It backs the header's
sign-in and the Code of Conduct report; no video entitlement uses it yet.
The Code of Conduct report
The report checks the EuroLeague ID session, lists games from the Competition Engine (locally the sample season when the engine cannot be reached), reads the reporter's name and email from the session's ID token, and emails the report to ELB. No email provider is chosen: a local site logs the email, and elsewhere Send answers 503.
WSC
WSC writes its key into the page, so the key is a public marker by nature; the SDK is downloaded only when a widget mounts.
Each package has its own reference page: @v4/wsc, @v4/eltv, @v4/ecal, @v4/analytics, @v4/cortex-sso, @v4/code-of-conduct. Every variable is listed in Environment variables.