The tracking library you tried to build yourself
Tracking that ships with the component.
Tag it once in the markup, and every place that component gets reused is already tracked. You don't have to remember a dataLayer call or wire up a click listener by hand.
MIT licensedself-hostableTypeScriptnpm packages
Because event instrumentation is real engineering effort
Four problems every tracking setup runs into eventually.
Tracking lives in the component
Tag a component once, and every instance is tracked.
The usual way: whether it's a GTM click listener bound to a CSS class or a developer's own dataLayer.push() call, the trigger lives outside the component, added by hand, once, by whoever happened to build that feature. Rename the class, restructure the markup, or just forget the push on the next component, and nothing errors. The event simply stops arriving, or never starts, and it can take weeks before anyone traces a reporting gap back to a change in an unrelated PR.
The walkerOS way: data-elb attributes live directly in the markup, right where the component is built. Tag the button component once, and every place that component is used, on this page or the next hundred, is already tracked. There is no separate tagging pass, and what ships stays in line with what's measured, even when the component is reused somewhere new.
<button data-elb="product" data-elb-product="name:Sneaker;price:89" data-elbaction="click:add" > Add to cart </button>
The attribute sits in the component's source instead of a config someone maintains elsewhere. Ship the component once, and every click it captures reaches every destination, without anyone touching a tag manager.
The vendor becomes a destination
Instrument once, and every vendor is just a mapping.
The usual way: tracking code calls a vendor's SDK directly, in the exact shape that vendor expects. Switch vendors, and every call site gets rewritten, or you add another tag, trigger and variable to a GTM container that's already too full.
The walkerOS way: the app only ever emits one event, named with a strict entity action grammar. Destination configs map it into GA4's shape, Meta's shape, or a warehouse row, so you can add, drop, or swap a destination without changing the app.
// same event, three destinations, zero app code touched
{
"destinations": {
"ga4": {
"config": { "mapping": { "product": { "view": { "name": "view_item" } } } }
},
"meta": {
"config": { "mapping": { "product": { "view": { "name": "ViewContent" } } } }
},
"warehouse": {
"config": { "mapping": { "product": { "view": { "name": "product_view" } } } }
}
}
}40+ destination adapters ship with the project. Removing GA4 or adding a warehouse means editing a block in this file instead of re-instrumenting every page.
Nothing leaves without your say
Consent is checked before data ever moves.
The usual way: data leaves the browser for a Google-owned tag manager before anyone's consent choice is even in the picture, and compliance is added afterward as a separate layer that may not catch everything.
The walkerOS way: every mapping rule can carry its own consent requirement, checked before an event reaches a destination, as part of the config that defines the event in the first place.
If consent is unresolved, the event queues or drops, depending on the destination and rule, and nothing is sent silently.
One place to look instead of three teams to ask
The fields that matter to your business aren't in any vendor's schema.
The usual way: GA4 enforces its own required fields on purchase, but it has never heard of your loyalty tiers, your cost centers, or your internal deal IDs. Whoever owns the tag manager checks those by hand against a handwritten spec, page by page, release by release, and manual checks miss things at scale.
The walkerOS way: your own fields go in the same typed contract as the standard ones, required the same way and validated the same way. A pull request that leaves loyalty_tier out fails before it merges, so no one has to remember to check.
{
"contract": {
"default": {
"events": {
"order": {
"complete": {
"properties": {
"data": { "required": ["total", "loyalty_tier"] }
}
}
}
}
}
}
}Frontend developers write the tagging against this file. Finance and analytics read reports from it. loyalty_tier is required here, and a validate step enforces it, replacing a manual check. Run walkeros validate --strict in CI, and a missing or misspelled field fails the build instead of showing up in a report someone reads weeks later.
The architecture
Three parts, with nothing hidden between them.
Every interaction becomes one typed event, once. What happens before and after is the whole system: where an event comes from, what it's allowed to carry, and where it's allowed to go.
sources
Browser DOM · dataLayer · CMPs · server
Where an interaction is captured: a click, a page view, a server-side call. Nothing is vendor-specific yet.
collector
Mapping · consent · routing
The one place the event is defined, checked against consent, and given a shape, before it reaches anything downstream.
destinations
GA4 · Meta · your warehouse · your own API
40+ adapters ship with the project. Swapping one out takes a config entry, and the event that reaches it stays the same.
walkerOS for ...
Tag a real website, live, in the browser.
In one hour, you tag one real page live in the Tag Mode extension and learn the mental model in practice rather than from a diagram: entity and action, properties read off the DOM, context that bubbles, and globals that don't.
60 min (45 + Q&A) · free · live, not recorded · bring your own page · Wednesday 10:00 CEST, date TBD, registrants are notified first
Beyond the repo
Run it yourself, or bring us in for the parts that need a team.
The software stays MIT licensed and self-hostable either way. These exist for the businesses that want a contract behind the pipeline their revenue reporting depends on.
community
Self-hosted
Everything on this page, yours to clone, read, and run. Support comes from GitHub Discussions and the community around the project.
- MIT licensed, no seat limits
- All sources, destinations, and transformers
- Community support, no response-time guarantee
fixed scope
Implementation
A project rather than a subscription. We align your teams on what to measure and why, define the entity-action event model and mapping config, then build it with your team and hand over a pipeline your engineers own from day one.
- Business questions mapped to entity action events
- Event model and mapping design for your stack
- Migration off an existing tag manager or CDP
- Custom source or destination builds
SLA
Support
A contract on top of the open-source project, for teams whose collector is on the critical path for revenue reporting or ad spend and can't run on best-effort community replies.
- Guaranteed response times, direct access to elbwalker engineers
- Priority fixes and security patches
- Version and upgrade guidance for production flows
No seat-based pricing on any tier: the software is the same MIT-licensed code whether you're on community or under contract.
FAQ
Questions we actually get.
Can't I just do this with Google Tag Manager?
GTM fans one event out to many vendor tags and has a consent trigger, so it overlaps with the job. As a collection layer it falls short in three ways. Nothing enforces a schema, so meaning lives in a variable-naming convention instead of a validated contract. Logic hides inside hand-written Custom HTML tags that the platform's own consent gate can't see into. And GTM is a router downstream of collection rather than a source of truth: something has to push structured data into dataLayer before GTM can act on it.
Server-side GTM doesn't close that gap. It solves a different, real problem by moving tags off the browser onto infrastructure you control, past blockers and Safari's ITP. The framework underneath stays the same, with a tag, trigger, and variable per vendor, maintained by hand per page, only now on a server you run. walkerOS replaces that framework, and it can run alongside a server-side GTM container if you already have one.
Some organizations rule out a Google-owned tag manager by policy. Others self-host on principle, so they don't have to add a new subprocessor to a DPA or send one to legal for review. walkerOS runs inside your own cloud, which settles both cases before they come up.
GTM handles fan-out well enough that most teams never look past it, until the tag count, the missing contract, and the developer work of filling dataLayer by hand for every new event become the problem. That is the same dependency on developers GTM was supposed to remove.
If we move collection to walkerOS, don't we lose the visual point-and-click tagging marketing uses?
No. GTM becomes one destination among many instead of the collection layer itself, so it goes back to the one job it was built for, firing tags, and gets easier to work in. Point-and-click tag additions still work for marketing, wired off the same typed events.
GTM no longer has to carry the collection logic: the custom scripts, hand-rolled consent checks, and schema hacks that pile up in a container once it's the only place data gets shaped. The container ends up smaller, with less code nobody wants to touch and more control over what's in it.
We want to build a tracking library in-house. Why would we adopt this instead?
Because adopting walkerOS doesn't ask you to stop building. Teams that build their own measurement platform still don't want to reinvent the collection layer from scratch. walkerOS is self-hosted and MIT licensed, so it slots in as one component under an architecture you own, without tying you to a platform vendor.
Own the thing your growth numbers depend on.