Unified Analytics Platform — Simplified HLD

Status: Target Architecture
Audience: Product, Engineering, Tagging Teams
Date: 2026-06-15


What We Have Today

Multiple Tagging Teams
├── Team A: Uses satellite.track("event_name", data)
├── Team B: Uses window.digitaldata = {...} (server-side injection)
├── Team C: Uses window.digitaldata = {...} (client-side mutation)
└── Team D: Custom event helpers

All paths lead to → Adobe Launch → Adobe Analytics

Problem: Same event tracked 4 different ways. Regressions happen when shared code changes.


What We Want Tomorrow

One Unified Contract Layer
    ↓
One Analytics SDK (tiny wrapper)
    ├── Option A: Call satellite.track correctly
    ├── Option B: Inject window.digitaldata correctly
    └── Option C: Both (policy decides)
    ↓
One Dispatch Path to Adobe Launch
    ↓
Production Validation and Monitoring

The Three Rules

  1. Contract First

    • Before any code, define the event shape in a schema.
    • Schema lives in packages/@analytics/contracts.
    • Zod validators generated automatically.
  2. One Entry Point

    • All teams use analytics.track(eventName, payload).
    • How it gets to Adobe is a policy decision, not app responsibility.
  3. Market and Brand Overlays

    • Base event contract.
    • Market-specific tweaks applied via config.
    • No app-level if-statements for ZA vs US.

Simple Architecture

[Diagram]

Step by Step How It Works

Step 1: Product/Tagging Team Defines Contract

File: packages/@analytics/contracts/events/search-filter.ts

import { z } from "zod";

export const SEARCH_FILTER_APPLIED = {
  name: "SEARCH_FILTER_APPLIED",
  version: "1.0.0",
  schema: z.object({
    filterId: z.string(),
    filterValue: z.string(),
    vehicleType: z.enum(["sedan", "suv", "truck"]),
    market: z.enum(["us-en", "ca-en", "za-en"]),
    timestamp: z.number(),
  }),
};

Step 2: Developer Uses SDK in Feature

File: apps/@nvc/search/components/filterPanel.tsx

import { analytics } from "@analytics/sdk";
import { SEARCH_FILTER_APPLIED } from "@analytics/contracts";

export function FilterPanel() {
  const handleFilterChange = (filter) => {
    analytics.track(SEARCH_FILTER_APPLIED.name, {
      filterId: filter.id,
      filterValue: filter.value,
      vehicleType: "sedan",
      market: "za-en",
      timestamp: Date.now(),
    });
  };

  return <div data-removed={handleFilterChange}>...</div>;
}

Step 3: SDK Does the Rest

File: packages/@analytics/sdk/index.ts

import { SEARCH_FILTER_APPLIED } from "@analytics/contracts";

export function track(eventName: string, payload: any) {
  // Validate against contract
  const contract = getContract(eventName);
  const validated = contract.schema.parse(payload); // throws if invalid

  // Apply tenant/market overlay
  const enriched = applyMarketPolicy(validated);

  // Dispatch via policy
  const policy = getDispatchPolicy(eventName);
  if (policy === "satellite") {
    window._satellite?.track(eventName, enriched);
  } else if (policy === "dataLayer") {
    window.digitaldata.push({
      event: eventName,
      data: enriched,
    });
  }

  // Log for observability
  logEvent(eventName, enriched);
}

What the Agent Automates

Your Prompt

Add analytics for search filter events in South Africa market. Events: filter-apply, filter-clear, filter-reset. Include filter ID, value, and result count.

What Agent Does (No Manual Coding)

  1. Creates Contract

    • Generates three event schemas with market overlay for ZA
  2. Updates Market Policy

    • Adds ZA-specific mapping rules
  3. Generates SDK Usage in App

    • Imports contract
    • Calls analytics.track() at right points
  4. Generates Tests

    • Unit test: contract validation
    • E2E test: payload snapshot vs expected
  5. Opens PR

    • Contract diff
    • Test evidence
    • Rollback note

You approve. Done.


Governance Layers

Layer 1: Contract Validation

Layer 2: Policy Routing

Layer 3: Market Overlay

Layer 4: Production Monitoring


Migration Path (Realistic)

Week 1-2: Foundation

Week 3-4: Consolidate

Week 5-6: Agent Setup

Week 7+: Autonomous


Realistic Timeline for Autonomy

Phase Effort Timeline You Get
Foundation Med 2 weeks Contract + SDK framework
Consolidation Med 2 weeks Teams migrated to one SDK
Agent MVP High 4 weeks Prompt → PR for new events
Production-Ready Med 2 weeks Drift detection + auto-merge policy
Total 10 weeks Full autonomous delivery

What Doesn't Change

  1. Adobe Launch still receives events
  2. Satellite.track() still works (called by SDK)
  3. window.digitaldata still works (managed by SDK, not direct mutation)
  4. Your existing Adobe rules and tags still apply
  5. No rip-and-replace

What Changes

  1. All events come through one SDK entry point
  2. Contracts are versioned and tracked in git
  3. Market behavior is config, not code
  4. Agent generates boilerplate code and tests
  5. Production validation detects drift automatically

Success Looks Like

Metric Before After
Time to add market to event 1-2 days 1 PR (2 hours)
Analytics regression rate 2-3 per month < 1 per month
Regression root cause identified 3-5 days Auto-detected in 1 hour
Cross-team event consistency 60% 99%
Manual coding per feature event 4-6 hours 0 hours

Next: Agent System Prompt

Once foundation is live, the agent works like this:

User: "Add tracking for loan calculator in US and ZA"
Agent: "I found calculator in nvc/financing. Need clarification:
  1. Should we track open, input-change, and submit? (yes/no)
  2. Include loan amount and term as payload? (yes/no)"
User: "yes, yes"
Agent: ✓ Generates contracts ✓ Updates policies ✓ Generates code
       ✓ Generates tests ✓ Opens PR
You: Review (2 mins) → Approve
System: Merge + Deploy + Monitor

This Architecture Supports

  1. ✓ Adobe Launch (current)
  2. ✓ GA4 (future - add adapter)
  3. ✓ Segment (future - add adapter)
  4. ✓ Custom webhook (future - add adapter)
  5. ✓ Server-side tagging (current - via dataLayer injection)
  6. ✓ Client-side tagging (current - via satellite.track)

One SDK, many dispatch options.


Questions for Your Tagging Team

  1. Which teams use satellite.track today? List them.
  2. Which teams use dataLayer injection today? List them.
  3. Are there custom event helpers? Where are they?
  4. Adobe Launch tags — any custom JavaScript transforms?

(Answers help agent understand existing patterns and generate compatible code.)


Questions for Your Engineering Team

  1. How do you currently test analytics events? (Manual? E2E? None?)
  2. How often do cross-app regression bugs happen?
  3. Which markets need analytics support in next 6 months?

(Answers help prioritize agent features.)


One Page Positioning

Today: Multiple teams, multiple approaches, fragile shared code, regressions when shared code changes.

Tomorrow: One contract, one SDK, one entry point. Agent generates code, validates with tests, delivers PR. Teams never manually code analytics again. Market rollouts are config changes, not code reviews.

Result: Faster, more reliable, fewer regressions, less manual work.