Skip to content
Closed

sync #539

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ All events follow this consistent structure:

```typescript
{
event: 'product view', // ENTITY ACTION format
name: 'product view', // ENTITY ACTION format
data: { // Entity-specific properties
id: 'P123',
name: 'Laptop',
Expand Down Expand Up @@ -488,7 +488,7 @@ it('processes events correctly', async () => {
});
await collector.push('page view', {});
expect(mockDestination.push).toHaveBeenCalledWith(
expect.objectContaining({ event: 'page view' }),
expect.objectContaining({ name: 'page view' }),
expect.any(Object),
);
});
Expand Down
283 changes: 213 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,235 @@
<p align="left">
<a href="https://elbwalker.com">
<img title="elbwalker" src='https://www.elbwalker.com/img/elbwalker_logo.png' width="256px"/>
<img title="elbwalker" src="https://www.elbwalker.com/img/elbwalker_logo.png" width="256px"/>
</a>
</p>

# Open-source event data collection and tag management

[Request Feature](https://github.com/elbwalker/walkerOS/issues/new) ·
[Report Bug](https://github.com/elbwalker/walkerOS/issues/new) ·
[Say hello](https://calendly.com/elb-alexander/30min)
# walkerOS: Open-Source tagging and event data collection

<div align="left">
<img src="https://img.shields.io/github/license/elbwalker/walkerOS" />
<a href="https://www.elbwalker.com/docs/"><img src="https://img.shields.io/badge/docs-www.elbwalker.com/docs/-yellow" alt="walkerOS Documentation"></a>
<a href="https://github.com/elbwalker/walkerOS/blob/main/LICENSE"><img src="https://img.shields.io/github/license/elbwalker/walkerOS" /></a>
<a href="https://www.elbwalker.com/docs/"><img src="https://img.shields.io/badge/docs-www.elbwalker.com/docs-yellow" alt="walkerOS Documentation"></a>
<a href="https://github.com/elbwalker/walkerOS/tree/main/apps/demos/react"><img src="https://img.shields.io/badge/React_demo-blue" alt="React demo"></a>

</div>

# What is walkerOS
walkerOS captures, structures, and routes events with built-in support for
consent management — all directly in your code. No fragile UI configs. No
black-box logic. Just **tracking infrastructure** you can version, test, and
trust.

walkerOS is a privacy-centric event data collection platform. It offers features
like data capturing,
[consent management](https://www.elbwalker.com/docs/consent_management/overview/),
data integration, and
[tag management](https://www.elbwalker.com/docs/destinations/event_mapping).
Fully configurable as code.
## Why walkerOS?

The project started as a web library
called&nbsp;<Link to="/docs/sources/walkerjs/">walker.js</Link> and has evolved
into a complete first-party tracking system.
- **Independence**: Make your data collection independent from single vendor
specifications to reduce complexity and extra code whenever you add or remove
a new service. Keep maintenance effort to a minimum.
- **Scalability**: DOM-based, component-level frontend tagging makes tracking
user behavior declarative, reusable, and easy to maintain.
- **Privacy-first approach**: Built-in consent handling and privacy controls
help you meet compliance from day one.
- **Type-safe tracking**: Built with TypeScript to catch tracking errors at
compile time, not in production. Get IDE autocomplete for APIs and destination
configs, prevent data structure mistakes.

## Packages Overview
## How it works

- **Sources** ([docs](https://www.elbwalker.com/docs/sources/),
[code](./packages/sources/)): For data creation and state management.
- **Destinations** ([docs](https://www.elbwalker.com/docs/destinations/),
[code](./packages/destinations/)): Initialize, map and share events to
third-party tools.
- **Utils** ([docs](https://www.elbwalker.com/docs/utils/),
[code](./packages/utils/)): Enhance data collection with shared utilities.
![walkerOS event flow](website/static/diagrams/walkerosflowdark.png)

## Why walkerOS?
## Quick Start

### npm

- **Sustainability**: Robust infrastructure for continuous data collection, even
amidst evolving data landscapes.
- **Privacy focus**: Strict privacy-by-design approach, in-build consent
management</Link> and various data protection features.
- **Complete data ownership**: Full control of your first-party data, no vendor
lock-in, and control of data processing.
- **Simplified data model**: Intuitive event model that streamlines data
collection, making analytics straightforward and efficient.
- **Flexible architecture**: Modular design adapting to your specific data needs
and allows growing step-by-step.

## How walkerOS operates

```mermaid
---
title: Basic infrastructure
---
flowchart LR
subgraph walkerOS
direction LR
subgraph Collection
Sources
end
subgraph Activation
Destinations
end
%%Utils
end
subgraph Tools
direction LR
storage["Storage"]
marketing["Marketing"]
analytics["Analytics"]
end
Sources --> Destinations
Destinations --> Tools
Install the required packages from npm:

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

Initialize walkerOS in your project:

```javascript
import { createCollector } from '@walkeros/collector';
import { createSource } from '@walkeros/core';
import { sourceBrowser } from '@walkeros/web-source-browser';

// Initialize walkerOS
export async function initializeWalker() {
const { collector } = await createCollector({
sources: {
browser: createSource(sourceBrowser, {
settings: {
pageview: true,
session: true,
elb: 'elb', // Browser source will set window.elb automatically
},
}),
},
destinations: {
console: {
push: (event) => console.log('Event:', event),
},
},
});
}
```

## Installation
### script tag

For websites without build tools, you can install from a CDN:

```html
<script>
// Load the collector, core utilities, and source
const { createCollector } = await import(
'https://cdn.jsdelivr.net/npm/@walkeros/collector/dist/index.mjs'
);
const { createSource } = await import(
'https://cdn.jsdelivr.net/npm/@walkeros/core/dist/index.mjs'
);
const { sourceBrowser } = await import(
'https://cdn.jsdelivr.net/npm/@walkeros/web-source-browser/dist/index.mjs'
);

// Initialize walkerOS
const { collector, elb } = await createCollector({
destinations: {
console: {
push: (event) => console.log('Event:', event),
},
},
sources: {
browser: createSource(sourceBrowser, {
settings: {
prefix: 'data-elb',
pageview: true,
session: true,
},
}),
},
});
</script>
```

## Example: React

Here's a quick look at how to integrate walkerOS into a React application.

**1. Create a walker setup file:**

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

declare global {
interface Window {
elb: WalkerOS.Elb;
walker: Collector.Instance;
}
}

export async function initializeWalker(): Promise<void> {
if (window.walker) return;

const { collector } = await createCollector({
run: false, // Defer run to handle route changes
sources: {
browser: createSource(sourceBrowser, {
settings: { pageview: true, session: true, elb: 'elb' },
}),
},
destinations: {
console: { push: (event) => console.log('Event:', event) },
},
});

window.walker = collector;
}

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

**2. Integrate into your App component:**

```tsx
// src/App.tsx
import { useLocation } from 'react-router-dom';
import { useEffect, useRef } from 'react';
import { initializeWalker } from './walker';

function App() {
const location = useLocation();
const hasInitialized = useRef(false);
const firstRun = useRef(true);

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

useEffect(() => {
// Use walker run to trigger page views on route changes
if (firstRun.current) {
firstRun.current = false;
return;
}
window.elb('walker run');
}, [location]);

// ... your app routes
}
```

**3. Tag your components:**

```tsx
// src/components/ProductDetail.tsx
import { tagger } from '../walker';

function ProductDetail({ product }) {
return (
<div {...tagger('product').data('id', product.id).get()}>
<h1>{product.name}</h1>
<button {...tagger().action('click', 'add').get()}>Add to Cart</button>
</div>
);
}
```

Start collecting data with our
[web](https://github.com/elbwalker/walkerOS/tree/main/packages/web/collector/)
or
[server](https://github.com/elbwalker/walkerOS/tree/main/packages/server/collector/)
source.
## Destinations

Destinations are the endpoints where walkerOS sends your processed events. They
transform standardized walkerOS events into the specific formats required by
analytics platforms, marketing tools, and data warehouses.

#### Web Destinations

- **[API](https://www.elbwalker.com/docs/destinations/web/api)** - Send events
to your own endpoints
- **[Google (gtag)](https://www.elbwalker.com/docs/destinations/web/gtag/)** -
GA4, Google Ads, and GTM integration
- **[Meta Pixel](https://www.elbwalker.com/docs/destinations/web/meta-pixel)** -
Facebook and Instagram advertising
- **[Plausible Analytics](https://www.elbwalker.com/docs/destinations/web/plausible)** -
Privacy-focused web analytics
- **[Piwik PRO](https://www.elbwalker.com/docs/destinations/web/piwikpro)** -
Privacy-focused analytics platform

#### Server Destinations

- **[AWS Firehose](https://www.elbwalker.com/docs/destinations/server/aws)** -
Amazon cloud services integration
- **[GCP BigQuery](https://www.elbwalker.com/docs/destinations/server/gcp)** -
GCP services and BigQuery
- **[Meta Conversions API](https://www.elbwalker.com/docs/destinations/server/meta-capi)** -
Server-side Facebook/Instagram tracking

## Contributing

Expand Down
11 changes: 11 additions & 0 deletions apps/demos/storybook/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# @walkeros/storybook-demo

## 0.1.0

### Minor Changes

- fixes

### Patch Changes

- Updated dependencies
- @walkeros/[email protected]

## 0.0.1

### Patch Changes
Expand Down
39 changes: 13 additions & 26 deletions apps/demos/storybook/eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format
import baseConfig from '@walkeros/eslint/web.mjs';
import storybook from 'eslint-plugin-storybook';

import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';
import { globalIgnores } from 'eslint/config';

export default tseslint.config(
[
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs['recommended-latest'],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
export default [
{
ignores: ['storybook-static/**'],
},
...baseConfig,
...storybook.configs['flat/recommended'],
{
files: ['**/*.stories.{js,ts,tsx}'],
rules: {
// Storybook-specific rule overrides if needed
},
],
storybook.configs['flat/recommended'],
);
},
];
2 changes: 1 addition & 1 deletion apps/demos/storybook/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@walkeros/storybook-demo",
"private": true,
"version": "0.0.1",
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
Loading