Skip to main content
Ask your AI

Web API Destination

Web Source code Package

The web API destination sends events from the browser to any HTTP endpoint, with customizable data transformation and transport methods.

Where this fits

Web API is a web destination in the walkerOS flow:

Sends events from the browser to any HTTP endpoint using fetch, XHR, or beacon transport with customizable request formatting.

Installation​

npm install @walkeros/web-destination-api

Configuration​

This destination uses the standard destination config wrapper (consent, data, env, id, ...). For the shared fields see destination configuration. Package-specific fields live under config.settings and are listed below.

Settings​

PropertyTypeDescriptionMore
url*stringThe HTTP endpoint URL to send events to
headersRecord<string, string>Additional HTTP headers to include with requests
methodstringHTTP method for the request
transformfunctionFunction to transform event data before sending
transport'fetch' | 'xhr' | 'beacon'Transport method for sending requests
* Required fields

Mapping​

This package does not define custom rule-level settings. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.

Examples

Custom payload

An order event is reshaped via a data mapping into a custom JSON body for the API endpoint.

Event
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "value": 555
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "235d0d7bd7a213f2",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000502,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "data": {
    "map": {
      "order_id": "data.id",
      "amount": "data.value",
      "tax": "data.taxes",
      "shipping_cost": "data.shipping",
      "currency": "data.currency",
      "event_name": "name",
      "user_id": "user.id"
    }
  }
}
Out
sendWeb("https://api.example.com/events", "{\"order_id\":\"0rd3r1d\",\"amount\":555,\"tax\":73.76,\"shipping_cost\":5.22,\"currency\":\"EUR\",\"event_name\":\"order complete\",\"user_id\":\"us3r\"}", {
  "headers": {
    "traceparent": "00-0a1b2c3d4e5f60718293a4b5c6d7e8f9-235d0d7bd7a213f2-01"
  },
  "transport": "fetch"
})

Entity action

A generic entity action event is forwarded to the configured API endpoint with the mapped data JSON body.

Event
{
  "name": "entity action",
  "data": {
    "string": "foo",
    "number": 1,
    "boolean": true,
    "array": [
      0,
      "text",
      false
    ]
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "lang": "elb"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "a4d76856b028d464",
  "trigger": "test",
  "entity": "entity",
  "action": "action",
  "timestamp": 1700000500,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "data": "data"
}
Out
sendWeb("https://api.example.com/events", "{\"string\":\"foo\",\"number\":1,\"boolean\":true,\"array\":[0,\"text\",false]}", {
  "headers": {
    "traceparent": "00-0a1b2c3d4e5f60718293a4b5c6d7e8f9-a4d76856b028d464-01"
  },
  "transport": "fetch"
})

Page view

A page view is POSTed to the configured API endpoint with the event data section as the JSON body.

Event
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "f0cc5f6fec3d8eeb",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000501,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "data": "data"
}
Out
sendWeb("https://api.example.com/events", "{\"domain\":\"www.example.com\",\"title\":\"walkerOS documentation\",\"referrer\":\"https://www.walkeros.io/\",\"search\":\"?foo=bar\",\"hash\":\"#hash\",\"id\":\"/docs/\"}", {
  "headers": {
    "traceparent": "00-0a1b2c3d4e5f60718293a4b5c6d7e8f9-f0cc5f6fec3d8eeb-01"
  },
  "transport": "fetch"
})

Modes​

import { startFlow } from '@walkeros/collector';
import { destinationAPI } from '@walkeros/web-destination-api';

const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        settings: {
          url: 'https://api.example.com/events',
        },
      },
    },
  },
});

Usage​

Basic usage​

import { startFlow } from '@walkeros/collector';
import { destinationAPI } from '@walkeros/web-destination-api';

const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        settings: {
          url: 'https://api.example.com/events',
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: 'Bearer your-token',
          },
        },
      },
    },
  },
});

Advanced usage with transform​

import { startFlow } from '@walkeros/collector';
import { destinationAPI } from '@walkeros/web-destination-api';

const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        settings: {
          url: 'https://api.example.com/events',
          transport: 'fetch',
          // data is the mapped data, or the event without a mapping
          transform: (data) =>
            JSON.stringify({ sent_at: Date.now(), payload: data }),
        },
      },
    },
  },
});

With batching​

Set config.batch to send events in one request per flush instead of one request per event. The options are in Batch scheduling.

Each flush is a single request whose body is a JSON array, one element per event. Mapping still applies per event, so an element is the event's mapped data when a rule produced some and the raw event otherwise. A transform runs per element, not once for the whole array. Batched requests carry no traceparent header: a batch can aggregate events from distinct traces, so there is no single identity to stamp.

Keep size small: the beacon transport is rejected by the browser once the bodies in flight exceed 64 KiB, and the default size is 1000 events. The fetch transport sends a request larger than that without keepalive, so it may be lost if the page unloads first. A full event is around 0.5 to 1 KiB.

import { startFlow } from '@walkeros/collector';
import { destinationAPI } from '@walkeros/web-destination-api';

const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        batch: { wait: 1000, size: 25 },
        settings: {
          url: 'https://api.example.com/events',
        },
      },
    },
  },
});

Transport methods​

  • fetch (default): fetch with keepalive, so the browser completes the request even when the page unloads first
  • xhr: a synchronous XMLHttpRequest
  • beacon: navigator.sendBeacon(), always a POST without the configured headers

A failed request is reported as a failed push: an error status, a network error, a timeout (10 seconds for fetch) or a beacon the browser refuses. The event counts as failed, reaches the dead-letter queue and the collector logs one ERROR line per cause and minute. A 4xx answer (other than 429) is not retried. A beacon over 64 KiB is rejected and not retried either.

A rule with silent: true sends nothing. Without settings.url the destination does not start and every push fails with the config code.

💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)