Skip to content
Data
Skill

/walkeros-understanding-destinations

Destinations receive processed events from the collector and deliver them to third-party tools (analytics, marketing, data warehouses).

BOOST
From plugin
walkeros
34822 skills
Install
$ npx -y skills add elbwalker/walkerOS --skill walkeros-understanding-destinations --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/walkeros-understanding-destinations

Context preview

The summary Claude sees to decide when to auto-load this skill.

Destinations receive processed events from the collector and deliver them to third-party tools (analytics, marketing, data warehouses).

SKILL.md

walkeros-understanding-destinations.SKILL.md
name: walkeros-understanding-destinations
description:
  Use when working with walkerOS destinations, understanding the destination
  interface, or learning about env pattern and configuration. Covers interface,
  lifecycle, env mocking, and paths.

Understanding walkerOS Destinations

Overview

Destinations receive processed events from the collector and deliver them to third-party tools (analytics, marketing, data warehouses).

**Core principle:** Destinations transform and deliver. They don't capture or process—that's sources and collector.

Destination Interface

See [packages/core/src/types/destination.ts](../../packages/core/src/types/destination.ts) for canonical interface.

| Method | Purpose | Required | | --------------------------- | -------------------------- | ------------ | | `init(context)` | Load scripts, authenticate | Optional | | `push(event, context)` | Transform and send event | **Required** | | `pushBatch(batch, context)` | Batch processing | Optional | | `destroy(context)` | Cleanup on shutdown | Optional | | `config` | Settings, mapping, consent | **Required** |

`destroy?: DestroyFn` — Optional cleanup method. Called during `command('shutdown')`. Use to close DB connections, flush buffers, or release SDK clients. Receives `{ id, config, env, logger }`.

The env Pattern

Destinations use dependency injection via `env` for external APIs. This enables testing without mocking.

// Destination defines its env type
export interface Env extends DestinationWeb.Env {
  window: {
    gtag: Gtag.Gtag;
    dataLayer: unknown[];
  };
}

// Destination uses env, not globals
async function push(event, context) {
  const { env } = context;
  env.window.gtag('event', mappedName, mappedData);
}

Testing with env

**REQUIRED SKILL:** See [testing-strategy](../walkeros-testing-strategy/SKILL.md) for full testing patterns.

import { mockEnv } from '@walkeros/core';
import { examples } from '../dev';

const calls: Array<{ path: string[]; args: unknown[] }> = [];
const testEnv = mockEnv(examples.env.push, (path, args) => {
  calls.push({ path, args });
});

await destination.push(event, { ...context, env: testEnv });

expect(calls).toContainEqual({
  path: ['window', 'gtag'],
  args: ['event', 'purchase', expect.any(Object)],
});

The env as observability seam

The env pattern is also the interception seam for trace-level vendor-call capture. At `trace` level the collector may attach an `observe` recorder under the `observe` key of the env, and `@walkeros/web-core`'s `getEnv` wraps the callables the destination declared as observable, recording each call. A destination that reaches its vendor through `getEnv(env)` is automatically observable; one that reaches a global directly, bypassing `env`, is not. This is one more reason to route every external call through `env`.

Rules that keep the seam intact:

  • **`init` keeps an injected env.** A client built in `init` (SDK client, auth

client, writer) is taken from `env` when present and created only otherwise (`env?.BigQuery ?? BigQuery`). Every key the mock env declares must be read as `env.<key>` in `src`.

  • **`simulation` names the request call** (`sendServer`,

`call:PubSub.topic.publishMessage`, `call:JSONWriter.appendRows`), not a constructor. The one recorder is `observeEnv` in `@walkeros/core`; it navigates constructors, factories and Promises, and records only the leaf.

  • **Trace-mode limit.** CLI and MCP simulate inject the mock env before `init`,

so a client built in `init` is recorded. Runtime trace mode wraps the env per push only, so calls through a client built in `init` are not recorded there.

  • **Client IP and user agent.** Server conversion-API destinations (Meta,

TikTok, Snapchat, Pinterest, Bing, Reddit, Criteo, X, Data Manager, Piwik PRO) expose `ip` and `userAgent` settings (`Mapping.Value | false`), defaulting to `['ingest.ip', 'event.user.ip']` and `['ingest.userAgent', 'event.user.userAgent']`, resolved with `getMappingValue(createMappingRoot(ingest, event), setting, { collector })`. `false` disables, an explicit mapped vendor field wins, each package carries its own few lines (no shared helper).

Destination Config

config: {
  settings: { /* destination-specific */ },
  mapping: { /* event transformation rules */ },
  data: { /* global data mapping */ },
  consent: { /* required consent states */ },
  policy: { /* processing rules */ },
  queue: boolean,  // queue events
  dryRun: boolean, // test mode
  queueMax: number,  // consent-queued events cap (default 1000)
  dlqMax: number,    // dead-letter queue cap (default 100)
}

Buffer bounds

Each destination keeps two internal buffers: `queuePush` (consent-denied events) and `dlq` (failed pushes). Both are size-bounded with FIFO drop-oldest eviction. Defaults: `queueMax: 1000`, `dlqMax: 100`. Set either on a destination's config to override per destination. Operators read drop counts from `collector.status.dropped[stepId('destination', id)]?.queue` (consent-denied evictions) and `?.dlq` (DLQ evictions). Build the key with `stepId()` from `@walkeros/core`. Point-in-time sizes stay on `collector.status.destinations[id].queuePushSize` / `dlqSize`.

`queuePush` drains back into the destination once consent allows delivery. The DLQ is never replayed: an event that reaches it is gone once it is evicted, which is what makes the delivery rules below worth getting right.

Delivery timeout

`config.timeout` bounds one delivery. A `push` or `pushBatch` that has not settled within it is abandoned, its events are routed to the DLQ and `failed` is incremented. The default is 10000 ms, applied whenever `timeout` is `0` or unset, so one slow destination never wedges the collector push.

**A destination's own client timeout has to fit inside it

Read more
Ships withwalkeros

From browser to BigQuery and ad platforms - warehouse-native, and ready for AI agents via MCP.

Get the whole plugin

Other skills on walkeros.