@aranova/tracking-cli
v0.7.2
Published
CLI for the Aranova tracking package — generates typed service unions from your dashboard taxonomy
Readme
@aranova/tracking-cli
CLI for the Aranova tracking packages. Generates a typed service union from a
business's dashboard-managed service taxonomy (so createSalesClient calls get
compile-time-checked service values) plus the business's registered Google
Ads / Meta tag IDs and R2 runtime config (ARANOVA_TRACKING_CONFIG) — ad-platform
config stays backend-driven instead of hand-typed.
Install it as a devDependency alongside @aranova/tracking-react or
@aranova/tracking-next:
npm install --save-dev @aranova/tracking-cligen
Fetches the active services, registered ad-platform IDs, and R2 tracking config reference for your business and writes a typed module.
npx @aranova/tracking-cli gen [--dev] [--endpoint <url>] [--api-key <key>] [--out <path>] [--check] [--env-file <path>]| Flag | Default | Notes |
| ------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --dev | off | Use the local dev backend (http://localhost:6969). Pre-flights reachability and fails fast if it's down. |
| --endpoint <url> | prod (https://aranovainternal-production.up.railway.app/tracking) | Overrides both --dev and the prod default. |
| --api-key <key> | ARANOVA_TRACKING_SECRET_KEY (else ARANOVA_TRACKING_API_KEY) from .env | Use a secret key (aranv_sk_…). Public keys are Origin-enforced and will 403 from Node. |
| --out <path> | src/aranova-services.ts | - writes to stdout. |
| --check | off | Don't write — compare the existing --out file against the freshly generated module. Exits 1 with a line diff if it's stale or missing, 0 if up to date. Great for CI. |
| --env-file <path> | — | Extra dotenv file to load (after .env and .env.local). |
Requires Node ≥ 20.
The key is read from .env via dotenv, so the typical invocation is just:
# .env (never commit a secret key)
ARANOVA_TRACKING_SECRET_KEY=aranv_sk_xxxxxxxxxxxxxxxxxxxxxxxxxx
npx @aranova/tracking-cli gen --devOutput
// AUTO-GENERATED by `@aranova/tracking-cli gen` — do not edit by hand.
// Re-run the command to refresh after changing services in the dashboard.
export const ARANOVA_SERVICES = [
{ key: "detail", label: "Detail" },
{ key: "oil", label: "Oil" },
{ key: "tires", label: "Tires" },
] as const;
export type AranovaService = (typeof ARANOVA_SERVICES)[number]["key"];
export const ARANOVA_SERVICE_LABELS: Record<AranovaService, string> = {
detail: "Detail",
oil: "Oil",
tires: "Tires",
};
// Legacy compatibility export. New installs use ARANOVA_TRACKING_CONFIG.
export const ARANOVA_GTAG_IDS = {
production: "AW-111111111",
test: "AW-18151802025",
} as const;
export const ARANOVA_TRACKING_CONFIG = {
cdnUrl: "https://demos.aranova.io/tracking-config/v1/<business>-production.json",
businessId: "<business>",
environment: "production",
} as const;ARANOVA_SERVICES carries each service's human-readable label (handy for a
dropdown), AranovaService is the union of keys, and ARANOVA_SERVICE_LABELS is
a typed key→label lookup. ARANOVA_GTAG_IDS and ARANOVA_CONFIG_URL remain
generated only so legacy imports keep compiling; do not wire them into new
installs. Use ARANOVA_TRACKING_CONFIG with createTracking,
createSalesClient (via getTrackingConfigRuntime), and
<AdPlatformTracking> so R2 remains the live authority and dashboard
tombstones clear old Google commands without a redeploy.
Bind the generated union when constructing the sales client:
import { createSalesClient } from '@aranova/tracking-next';
import type { AranovaService } from './aranova-services';
const sales = createSalesClient<AranovaService>({
apiKey: process.env.ARANOVA_TRACKING_SECRET_KEY!,
endpoint: process.env.ARANOVA_TRACKING_ENDPOINT!,
});
await sales.record({ service: 'tires', /* 'tirez' is a compile error */ ... });Generated types can lag the dashboard safely — the backend validates service
on every write and returns 422 for an unknown key. Re-run gen to refresh.
A common setup is a package.json script:
"scripts": { "gen:services": "aranova-tracking gen --dev" }See docs/tracking-package/sales-tracking.md
for the full sales/conversions guide.
list
Print the active services to stdout — a quick way to see a business's taxonomy without generating a file.
npx @aranova/tracking-cli list [--dev] [--endpoint <url>] [--api-key <key>] [--json] [--env-file <path>]KEY LABEL
oil Oil
tires TiresPass --json for a machine-readable [{ "key", "label" }] array. list shares
the --dev / --endpoint / --api-key / --env-file flags with gen.
gtags
Print the registered Google Ads tag IDs to stdout:
npx @aranova/tracking-cli gtags [--dev] [--endpoint <url>] [--api-key <key>] [--json] [--env-file <path>]LABEL GTAG_ID
production AW-111111111
test AW-18151802025CI drift check
"scripts": { "gen:services:check": "aranova-tracking gen --check" }gen --check regenerates in memory and compares against the committed file,
exiting non-zero with a diff if they differ — so CI fails when the generated
types lag the dashboard, without rewriting the file.
Exit codes
gen exits non-zero with a clear message on: missing/invalid key (401), a key
not permitted for the business (403), an unreachable --dev backend, a network
failure, or an unwritable --out path. With --check it also exits non-zero when
the --out file is stale or missing (it is never written in --check mode). An
empty service list is not an error — it emits an empty array + empty labels map
and warns. An empty/partial gtag map (or a backend without the /gtags route)
is also not an error — it emits {} as const / the partial map with a note.
