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

# Quickstart

Get started with walkerOS in minutes. These examples provide working code that you can copy, paste, and run. The step 2 example is maintained in our [quickstart app](https://github.com/elbwalker/walkerOS/tree/main/apps/quickstart) and tested with every release.

This quickstart uses [integrated mode](/preview/pr-749/docs/getting-started/modes/integrated.md): the collector runs inside your own code. You can switch how you package it later, see [operating modes](/preview/pr-749/docs/getting-started/modes.md).

Working with an AI assistant?

`@walkeros/mcp` runs locally without an account. Install the plugin and describe the flow you want: [With an AI assistant](/preview/pr-749/docs/apps/mcp.md).

## 1. Install packages[​](#1-install-packages "Direct link to 1. Install packages")

Install the collector and the browser source from npm:

```bash
npm install @walkeros/collector @walkeros/web-source-browser
```

## 2. Create basic setup[​](#2-create-basic-setup "Direct link to 2. Create basic setup")

Send your first event with a collector and a single console destination. This first snippet stays DOM-free so it runs in Node; the browser source for automatic DOM capture comes in the next step.

```javascript
import { startFlow } from '@walkeros/collector';

const { elb } = await startFlow({
  destinations: {
    console: {
      code: {
        type: 'console',
        config: {},
        push: (event) => console.log('Event:', event.name),
      },
    },
  },
});

await elb({ name: 'page view', data: { title: 'Home' } });
// -> logs: Event: page view
```

## 3. Add destinations[​](#3-add-destinations "Direct link to 3. Add destinations")

Install destination packages and add them to your setup:

```bash
npm install @walkeros/web-destination-gtag @walkeros/web-destination-api
```

```javascript
import { startFlow } from '@walkeros/collector';
import { sourceBrowser } from '@walkeros/web-source-browser';
import { destinationGtag } from '@walkeros/web-destination-gtag';
import { destinationAPI } from '@walkeros/web-destination-api';

export async function initializeWalker() {
  const { collector } = await startFlow({
    sources: {
      browser: {
        code: sourceBrowser,
        config: {
          settings: {
            pageview: true,
            elb: 'elb',
          },
        },
      },
    },
    destinations: {
      // Send events to your API
      api: {
        code: destinationAPI,
        config: {
          settings: {
            url: 'https://your-api.com/events',
          },
        },
      },

      // Send to Google Analytics 4
      ga4: {
        code: destinationGtag,
        config: {
          settings: {
            ga4: { measurementId: 'G-XXXXXXXXXX' },
          },
        },
      },
    },
  });

  window.walker = collector;
}
```

## 4. Add consent management[​](#4-add-consent-management "Direct link to 4. Add consent management")

Add consent requirements to your destinations. This replaces `initializeWalker` from step 3 and keeps its imports. Until a destination's required consent is granted, its events wait in the destination's queue and are sent once the consent arrives, unless a new `walker run` starts first, which empties the queue. The consent handlers wait for the flow to start, so your banner can call them at any time, also right after `initializeWalker()` to restore a stored choice.

```javascript
let walkerReady;

// Starts the flow once, later calls return the same promise
export function initializeWalker() {
  walkerReady ??= startWalker();
  return walkerReady;
}

async function startWalker() {
  const { collector } = await startFlow({
    sources: {
      browser: {
        code: sourceBrowser,
        config: {
          settings: {
            pageview: true,
            elb: 'elb',
          },
        },
      },
    },
    destinations: {
      // API destination - requires functional consent
      api: {
        code: destinationAPI,
        config: {
          settings: {
            url: 'https://your-api.com/events',
          },
          consent: {
            functional: true,
          },
        },
      },

      // GA4 - requires analytics consent
      ga4: {
        code: destinationGtag,
        config: {
          settings: {
            ga4: { measurementId: 'G-XXXXXXXXXX' },
          },
          consent: {
            analytics: true,
          },
        },
      },
    },
  });

  window.walker = collector;
}

// Call these from your consent banner when the user accepts or denies
export async function handleConsentAccept() {
  await initializeWalker();
  return window.elb('walker consent', {
    functional: true,
    analytics: true,
    marketing: true,
  });
}

export async function handleConsentDeny() {
  await initializeWalker();
  return window.elb('walker consent', {
    functional: true,
    analytics: false,
    marketing: false,
  });
}
```

## See your event[​](#see-your-event "Direct link to See your event")

The step 2 setup runs directly in Node. Save it as `index.mjs` (the import and top-level `await` need ES modules) and run:

```bash
node index.mjs
```

You should see:

```bash
Event: page view
```

That is the whole loop: an event pushed with `elb` reaching a destination. The browser setups in steps 3 and 4 have no console destination: once your app runs, check the requests to your API and to GA4 in your browser's network tab. To test flows offline with the CLI instead, see [bundled mode](/preview/pr-749/docs/getting-started/modes/bundled.md#see-your-event).

## Next steps[​](#next-steps "Direct link to Next steps")

* **[Send it to GA4](/preview/pr-749/docs/getting-started/ga4-ecommerce.md)**: the same event arriving live in GA4 DebugView
* **[DOM-based tagging](/preview/pr-749/docs/sources/web/browser/tagging/html-attributes.md)**: automatic tracking via data-elb attributes
* **[Event mapping](/preview/pr-749/docs/mapping.md)**: transform events before sending
* **[Operating modes](/preview/pr-749/docs/getting-started/modes.md)**: choose how to package and deploy
