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

# Next.js Quickstart

This guide shows you how to integrate walkerOS into your Next.js application. Most setup is identical to React - check the [React quickstart guide](https://www.walkeros.io/docs/getting-started/quickstart/react.md) for more details.

## Installation[​](#installation "Direct link to Installation")

Install the required packages:

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

## Setup[​](#setup "Direct link to Setup")

### 1. Walker initialization[​](#1-walker-initialization "Direct link to 1. Walker initialization")

Create the walker initialization file:

```
// walker/index.ts
import type { Collector, WalkerOS } from '@walkeros/core';
import { startFlow } from '@walkeros/collector';
import { createTagger, sourceBrowser } from '@walkeros/web-source-browser';

// Global type declarations
declare global {
  interface Window {
    elb: WalkerOS.Elb;
    walker: Collector.Instance;
  }
}

export async function initializeWalker(): Promise<void> {
  // Skip initialization if already done
  if (window.walker) return;

  // Create collector with run: false for manual pageview control
  const { collector, elb } = await startFlow({
    run: false,
    consent: { functional: true },
    sources: {
      browser: {
        code: sourceBrowser,
        config: {
          settings: {
            pageview: true,
            session: true,
            elb: 'elb',
          },
        },
      },
    },
    destinations: {
      // Your destinations - add console for testing
      console: {
        code: {
          type: 'console',
          config: {},
          push(event, data) {
            console.log('Event:', event, data);
          },
        },
      },
    },
  });

  // Set global window object
  window.walker = collector;
}

// Tagger helper for easy component tagging
const taggerInstance = createTagger();

export function tagger(entity?: string) {
  return taggerInstance(entity);
}
```

### 2. App integration[​](#2-app-integration "Direct link to 2. App integration")

For Next.js applications, use the Next.js router events:

```
// pages/_app.tsx
import { useRouter } from 'next/router';
import { useEffect, useRef } from 'react';
import { initializeWalker } from '../walker';

export default function App({ Component, pageProps }) {
  const router = useRouter();
  const hasInitialized = useRef(false);
  const firstRun = useRef(true);

  useEffect(() => {
    // Prevent double execution
    if (!hasInitialized.current) {
      initializeWalker();
      hasInitialized.current = true;
    }
  }, []);

  useEffect(() => {
    const handleRouteChange = () => {
      if (firstRun.current) {
        firstRun.current = false;
        return;
      }
      window.elb('walker run');
    };

    // Next.js route events
    router.events.on('routeChangeComplete', handleRouteChange);

    // Call on initial load
    handleRouteChange();

    return () => {
      router.events.off('routeChangeComplete', handleRouteChange);
    };
  }, [router.events]);

  return <Component {...pageProps} />;
}
```

For Next.js 13+ with App Router:

```
// app/layout.tsx
'use client';

import { usePathname } from 'next/navigation';
import { useEffect, useRef } from 'react';
import { initializeWalker } from './walker';

export default function RootLayout({ children }) {
  const pathname = usePathname();
  const hasInitialized = useRef(false);
  const firstRun = useRef(true);

  useEffect(() => {
    // Prevent double execution
    if (!hasInitialized.current) {
      initializeWalker();
      hasInitialized.current = true;
    }
  }, []);

  useEffect(() => {
    if (firstRun.current) {
      firstRun.current = false;
      return;
    }

    window.elb('walker run');
  }, [pathname]);

  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}
```

## Component usage[​](#component-usage "Direct link to Component usage")

Component usage is identical to React. Use the tagger helper and manual events:

```
import { tagger } from '../walker';

function ProductPage({ product }) {
  // Manual event tracking
  useEffect(() => {
    window.elb('product view', {
      id: product.id,
      name: product.name,
      price: product.price,
    });
  }, [product]);

  return (
    <div
      {...tagger('product')
        .action('view')
        .data('id', product.id)
        .data('name', product.name)
        .get()}
    >
      <h1>{product.name}</h1>
      <button
        {...tagger().action('add').get()}
        onClick={() => window.elb('product add', { id: product.id })}
      >
        Add to Cart
      </button>
    </div>
  );
}
```

info

When using the `tagger` helper, make sure to call .get() at the end of the chain.

## Testing[​](#testing "Direct link to Testing")

During walker initialization, we added a console destination. This will output events to the console. Open your browser's developer console to see tracked events:

```
Event: "product view", { id: 123, name: "Premium Chocolate", price: 12.99 }
```

## Best practices[​](#best-practices "Direct link to Best practices")

1. **Use tagger**: Clean component tagging with the tagger helper
2. **Minimal Next.js code**: Keep Next.js integration as simple as possible
3. **Trust walkerOS**: No need for custom error handling or state management
4. **Direct integration**: No providers needed, integrate directly in \_app or layout
5. **Test with console**: Use console destination during development

## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting")

### Events not firing[​](#events-not-firing "Direct link to Events not firing")

1. Check that `window.walker` is set in the browser console
2. Verify data attributes are correctly formatted (use `data-elb` prefix)
3. Ensure walker initialization completed (window\.walker.allowed must be `true`)
4. Check browser console for any error messages

### Route changes not tracked[​](#route-changes-not-tracked "Direct link to Route changes not tracked")

1. Check that `walker run` is called on route changes
2. Ensure firstRun logic is preventing double execution on initial load
3. Verify router event listeners are working correctly

### TypeScript errors[​](#typescript-errors "Direct link to TypeScript errors")

Make sure you've added the global type declarations in your walker initialization file.

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

* Configure [destinations](https://www.walkeros.io/docs/destinations.md) for your analytics tools
* Set up [consent management](https://www.walkeros.io/docs/guides/consent.md)
* **[Send it to GA4](https://www.walkeros.io/docs/getting-started/ga4-ecommerce.md)**: the same event arriving live in GA4 DebugView
* **[Operating modes](https://www.walkeros.io/docs/getting-started/modes.md)**: choose how to package and deploy
