Decisions
ADR 0005: k.js Relay — Micro-Modules, Hybrid Edge, and CMP Product (Accepted)
Status
Accepted — 16 Jun 2026. Product and architecture defaults for Phase 2+ First-party tag relay.
Context
Phase 2+ introduces Kobico Relay: a first-party (or optional third-party) loader (k.js), edge-delivered micro-modules, and server-side fan-out to Meta CAPI, TikTok Events API, GA4 Measurement Protocol, and Google Ads Enhanced Conversions.
Requirements gathered from board/product discussion:
- First-party CNAME as default; third-party loader URL only when client opts in or cannot set DNS yet.
- Dynamic micro-modules — small core + platform listeners — to protect PageSpeed, edge cost, and maintainability (global vs regional e-commerce adapters).
- Hybrid Cloudflare + GCP — edge for TLS/cache/manifest; Cloud Run for relay logic aligned with existing stack.
- Consent included — clients must not be sent to buy a CMP elsewhere before Relay works; Kobico CMP is the default; popular third-party CMPs remain supported via integration.
- Global CMP partnerships — pursue formal partnerships with major CMP vendors; until then, Kobico may bundle/resell CMP seats at no separate client charge (cost in Relay/media-tech bundle).
Decision
1. Loader delivery
| Mode | URL pattern | Default? |
|---|---|---|
| First-party | https://metrics.{client-domain}/k.js?tenant_id=… |
Yes — Relay SKU default |
| Third-party | https://tracking.kobi.com/k.js?tenant_id=… |
Opt-in only — labeled “reduced tracking mode” in portal |
Client adds one CNAME (first-party) or one script tag (third-party). Same backend manifest and modules.
2. Micro-module delivery — Pattern A (bootstrap + cached chunks)
| Artifact | Role |
|---|---|
k.js |
Thin bootstrap — reads tenant_id, fetches manifest |
| Manifest | Edge KV/D1 — vertical, platform, enabled modules, consent profile |
k-core.js |
Static baseline (≤3 KB gzipped) — consent bridge, click IDs, relay POST, Consent Mode v2 |
| Global listeners | e.g. Shopify, WooCommerce — src/listeners/global/ |
| Local listeners | e.g. ikas, Ticimax, IdeaSoft — src/listeners/local/ |
Marketing/analytics modules load after consent grant. Immutable versioned chunk URLs; long cache at edge.
Not chosen: edge-stitched single bundle per tenant (Pattern B) or per-tenant CI bundles (Pattern C) — revisit only if Pattern A fails performance SLOs.
3. Cloud split — hybrid (locked)
| Layer | Platform |
|---|---|
| Custom hostnames, TLS, WAF, CDN | Cloudflare (SSL for SaaS) |
| Manifest + static module routing | Cloudflare Workers + KV/D1 |
| Relay ingest, dedup, fan-out, audit | GCP Cloud Run (europe-west1) |
| Secrets, tenant registry, BQ telemetry | GCP (existing) |
Workers-only relay rejected for v1 — tokens and QC traceability live on GCP today (relay doc § Cloud).
4. Tenant manifest (minimum fields)
| Field | Purpose |
|---|---|
tenant_id |
Identity |
delivery_mode |
first_party | third_party |
vertical |
Event schema (tourism, ecommerce_tr, …) |
platform |
Primary local listener key (ikas, ticimax, …) |
enabled_modules |
Resolved module list for edge |
consent_profile |
tr_kvkk, eea_strict, … |
cmp_mode |
See CMP decision below |
5. CMP product — Kobico CMP default; partnerships on the table
| Tier | Product | Client experience |
|---|---|---|
| Default | Kobico CMP (banner with k.js) |
Included in Relay SKU — no separate CMP purchase step |
| Integration | Client BYO CMP (Cookiebot, OneTrust, iubenda, TCF) | k.js listens; client keeps existing vendor |
| Partnership / bundle | Kobico-resold global CMP | No separate client invoice; cost in bundle; pursue formal partnership with vendor |
| GTM hybrid | CMP + loader via GTM | Agency clients |
Default onboarding: cmp_mode = kobi_cmp. Client approves privacy policy URL and banner copy in portal — never “go buy a CMP, then return.”
Global CMP partnership program (active): Leadership to pursue partnerships with Cookiebot, OneTrust, iubenda, CookieYes, and comparable vendors — co-marketing, support escalation, portfolio pricing. Until partnership closes, Kobico may subscribe at portfolio level and allocate per-tenant seats (bundled resell) without exposing a separate CMP checkout to clients.
6. Phased relay delivery
| Sub-phase | Ships | Client value |
|---|---|---|
| 2a | k-core + relay POST + Kobico CMP | CNAME + one script; CAPI fan-out; no platform listeners yet |
| 2b | Global listeners (Shopify, WooCommerce) | Auto checkout events |
| 2c | Local listeners (ikas, Ticimax, IdeaSoft) | TR e-commerce depth |
| 2d | Bundled third-party CMP + partnership integrations | Enterprise / legal preference |
v1 remains implementation guide + browser pixel; Relay does not block Phase 2 Meta/TikTok CAPI via CTS.
Consequences
- Positive: Single onboarding motion (DNS + script + consent); bounded JS payload; aligns with GCP topology; consent not outsourced to client procurement.
- Negative: Kobico owns CMP legal copy review and banner maintenance; partnership pipeline is ongoing exec work; hybrid ops (CF + GCP).
- Follow-up: Update relay spec, portal Screen (Phase 2+), provisioning
tracking_relayblock; QC rules for third-party delivery mode and missing consent snapshot.