Git-Native Config
Your entire tracking configuration is a TypeScript file. Review it in PRs. Test it in CI. Roll it back with git revert.
import type { CollectorConfig } from "@junctionjs/core";
import { ga4 } from "@junctionjs/destination-ga4";
import { amplitude } from "@junctionjs/destination-amplitude";
import { meta } from "@junctionjs/destination-meta";
import { contracts } from "./contracts";
export const config: CollectorConfig = {
name: "orbit-supply",
environment: "production",
// ① Consent: queue events while user decides, respect privacy signals
consent: {
defaultState: {}, // No consent assumed on load
queueTimeout: 10_000, // 10s queue before dropping
respectDNT: true, // Honor Do Not Track
respectGPC: true, // Honor Global Privacy Control
},
// ② Destinations: each declares its own consent requirements
destinations: [
{
destination: ga4,
config: { measurementId: "G-XXXXXXXXXX", consentMode: true },
// consent: ["analytics"] ← inherited from destination
},
{
destination: amplitude,
config: { apiKey: "amp_xxxxxxxxxxxx", mode: "client" },
},
{
destination: meta,
config: { pixelId: "123456789" },
// consent: ["marketing"] ← inherited from destination
},
],
// ③ Contracts: Zod schemas that validate every event at runtime
contracts,
// ④ Debug: in-page panel in dev, zero overhead in production
debug: process.env.NODE_ENV !== "production",
};Queue events while consent is pending. Respect DNT and GPC browser signals. Configure per-destination consent categories.
Each destination is a typed plugin that declares its own consent requirements. Add or remove one in a PR — no UI required.
Zod schemas validated at runtime. Invalid events are caught immediately, not discovered weeks later in a dashboard.
In-page debug panel in development. Zero runtime overhead in production. Toggle with Ctrl+Shift+J.
What This Replaces
GTM / Adobe Launch
Every change requires navigating 4+ screens. No PR. No CI. No rollback button.
- 1.Log into the GTM web UI, navigate to the correct workspace
- 2.Create a tag — pick the right template, configure fields in form inputs
- 3.Create a trigger — select conditions from dropdown menus
- 4.Link tag to trigger, hope the variable names match your dataLayer
- 5.Test in Preview mode (opens a separate debug window)
- 6.Click "Submit" — no PR, no review, no CI tests, no rollback button
- 7.Pray nobody broke the dataLayer contract in a code deploy
Junction
Everything is TypeScript in your repo. Ships with your app. Rolls back with git.
- 1.Edit
junction-config.tsin your IDE - 2.TypeScript catches misconfigured destinations at compile time
- 3.Open a PR — teammates review the exact diff
- 4.CI runs contract tests against your Zod schemas
- 5.Merge — deploys automatically with your app
- 6.Something wrong?
git revertrestores the previous config
Adding Amplitude: The Diff
This is the entire change required to add Amplitude to your analytics stack. 8 lines. In a PR. Reviewed, tested, and deployed with your code.
destinations: [{ destination: ga4, config: { measurementId: "G-XXX" } },+ {+ destination: amplitude,+ config: {+ apiKey: process.env.AMPLITUDE_KEY,+ mode: "client",+ eventNameFormat: "Title Case",+ },+ },],
With Junction
8 lines of TypeScript → PR → CI → merge. Done. Reviewable, testable, reversible.
With GTM
Create tag → create trigger → configure variables → link → preview → submit. 6 steps. No PR. No CI. No rollback.