> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# Browser source commands

The browser source provides an enhanced `elb` function that supports browser-specific features like DOM interaction, elbLayer communication, and automatic initialization. These commands are processed by the browser source translation layer before being passed to the collector.

<!-- -->

## elb[​](#elb "Direct link to elb")

The browser source provides an enhanced `elb` function that supports flexible argument patterns and browser-specific features.

```
// Import from browser source
import { elb } from '@walkeros/web-source-browser';
window.elb = elb;

// Or define the elb function manually in the browser
function elb() {
(window.elbLayer = window.elbLayer || []).push(arguments);
}
```

Usage options:

```
elb("entity action", data, ...);
elb({event: "entity action", data: { foo: "bar"}});
```

During initialization the source installs its writer at `window[settings.elb]` (default `elb`). The name is a single slot and belongs to the first source that installs it: a source that finds the name held by another one logs an error, skips the install, and keeps capturing through its own `push`. Set `elb: false` to install no window property at all, which is the posture for an embedded source that should leave no page-window footprint. Calls return a promise that resolves with the processing result.

See [Multiple sources on one page](https://www.walkeros.io/docs/sources/web/browser.md#multiple-sources-on-one-page) for running several sources side by side.

### elbLayer processing[​](#elblayer-processing "Direct link to elbLayer processing")

`window.elbLayer` is an append-only queue: entries are recorded and never removed, so inspecting the array always shows the full input history. Both `window.elb(...)` and `window.elbLayer.push(...)` are processed through the same translation layer.

Processing order:

* `walker` commands apply as soon as the source is initialized, so a queued `walker consent` takes effect before any queued events.
* Events are processed once the source has started (after the first `walker run`), in the order they were pushed.
* From then on, all entries are processed strictly in push order.

One named layer belongs to one source, because a queue is drained once. The first source to adopt `window[settings.elbLayer]` keeps it, and a source that asks for a name another one already adopted logs an error and runs without a layer, capturing from its scope as usual. Parallel flows use separate layer names or `elbLayer: false`.

## config[​](#config "Direct link to config")

Configure the browser source during initialization through `startFlow`. These settings control browser-specific behavior:

```
import { startFlow } from '@walkeros/collector';
import { sourceBrowser } from '@walkeros/web-source-browser';

const { collector } = await startFlow({
sources: {
browser: {
code: sourceBrowser,
config: {
  settings: {
    elb: 'elb', // Name for the global elb function, or false to install none
    elbLayer: true, // Enable elbLayer for async command queuing
    pageview: true, // Trigger a page view event by default
    prefix: 'data-elb', // Attributes prefix used by the walker for DOM scanning
  },
},
},
},
});
```

note

Browser source configuration must be done during initialization. Settings like `prefix` and `elbLayer` cannot be changed after the source is created. Session tracking is provided by the separate `@walkeros/web-source-session` source.

## run[​](#run "Direct link to run")

A `run` initializes the browser source and triggers automatic DOM scanning and event setup. It will:

* Initialize DOM event listeners
* Scan for `data-elb` attributes
* Trigger a `page view` event by default
* Process the `elbLayer` stack

```
elb('walker run');
```

A run accepts a partial state parameter:

```
elb('walker run', { group: 'group1d' });
```

### Virtual pageviews in SPAs[​](#virtual-pageviews-in-spas "Direct link to Virtual pageviews in SPAs")

Use `walker run` to trigger virtual pageviews when navigating between routes in Single Page Applications. Call it on each route change to fire a new `page view` event and re-scan the DOM:

```
// React Router example
useEffect(() => {
  window.elb('walker run');
}, [location]);

// Next.js App Router example
useEffect(() => {
  window.elb('walker run');
}, [pathname]);
```

tip

For SPAs, use `walker run` for route changes (triggers pageview), and `walker init` for dynamically loaded content within the same page (no pageview).

## init[​](#init "Direct link to init")

Re-initializes event listeners on one or multiple target elements without triggering a page view. Useful for dynamically loaded content like product lists, infinite scroll, or wizard steps.

```
elb('walker init', element); // Single element
elb('walker init', [element1, element2]); // Multiple elements
```

This command is essential for Single Page Applications (SPAs) where content is added dynamically after the initial page load.

Re-initializing a scope clears and rebuilds that scope's `pulse`, `wait`, `hover`, `scroll`, `visible`, and `impression` triggers. The `load` trigger fires (again) on each call.

This applies to every action-tagged element in the target's subtree, including elements that are already tracked from an earlier scan. So the SPA pattern of re-tagging an existing element and re-initializing it works: the updated attribute values are read fresh and the `load` trigger fires again.

```
// The step element was already tracked by the initial page scan.
const step = document.getElementById('checkout-step');
step.setAttribute('data-elb-checkout', 'step:3');
elb('walker init', step); // fires 'checkout view' again, now with step: 3
```

Each `walker run` does the same for the whole document, so a virtual pageview also re-fires document `load` triggers.

```
// After loading new products via AJAX
const productList = document.getElementById('product-list');
fetchProducts().then(() => {
  elb('walker init', productList);
});
```

tip

Use `walker init` after adding new DOM elements with `data-elb` attributes. Unlike `walker run`, this does not trigger a page view event - it only enables tracking on the specified elements.

For content that a SPA injects repeatedly into the same container, the [`data-elbobserve`](https://www.walkeros.io/docs/sources/web/browser/tagging/html-attributes.md#auto-init-with-data-elbobserve) attribute is a declarative alternative: mark the container once and injected tagged content is registered automatically, without a `walker init` call after each injection.

## run vs init comparison[​](#run-vs-init-comparison "Direct link to run vs init comparison")

| Command       | Triggers pageview | Re-scans DOM         | Use case                                                    |
| ------------- | ----------------- | -------------------- | ----------------------------------------------------------- |
| `walker run`  | Yes               | Full page            | SPA route changes, virtual pageviews                        |
| `walker init` | No                | Target elements only | Dynamically loaded content (product lists, infinite scroll) |

## Integration with collector[​](#integration-with-collector "Direct link to Integration with collector")

Browser source commands work in conjunction with [collector commands](https://www.walkeros.io/docs/collector/commands.md). The browser source handles DOM-specific functionality while the collector manages destinations, consent, and user data.

Common workflow:

1. Configure browser source in `startFlow`
2. Browser source automatically initializes (or use `walker run` for manual control)
3. Use `walker init` for dynamic content
