skills/walkeros-mapping-configuration/SKILL.md
Use when configuring walkerOS event mappings for specific use cases. Provides recipes for GA4, Meta, custom APIs, and common transformation patterns.
npx skillsauth add elbwalker/walkeros walkeros-mapping-configurationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Read understanding-mapping first for core concepts.
| I want to... | Use this pattern |
| ------------------------------ | ----------------------------------------------------- |
| Rename event | { name: 'new_name' } |
| Extract nested value | 'data.nested.value' |
| Set static value | { value: 'USD' } |
| Transform value | { fn: (e) => transform(e) } |
| Build object | { map: { key: 'source' } } |
| Process array | { loop: ['source', { map: {...} }] } |
| Gate by consent | { key: 'data.email', consent: { marketing: true } } |
| First defined value (fallback) | [{ key: 'data.sku' }, { key: 'data.id' }] |
| Add a field to a default rule | { extend: { data: { map: { x: 'path' } } } } |
| Drop a field from output | { remove: ['field.path'] } |
Product view → view_item:
product: {
view: {
name: 'view_item',
data: {
map: {
currency: { value: 'USD' },
value: 'data.price',
items: {
loop: [
'nested',
{
map: {
item_id: 'data.id',
item_name: 'data.name',
item_category: 'data.category',
price: 'data.price',
quantity: { value: 1 },
},
},
],
},
},
},
},
}
Order complete → purchase:
order: {
complete: {
name: 'purchase',
data: {
map: {
transaction_id: 'data.orderId',
value: 'data.total',
currency: 'data.currency',
items: {
loop: [
'nested',
{
map: {
item_id: 'data.id',
item_name: 'data.name',
price: 'data.price',
quantity: 'data.quantity',
},
},
],
},
},
},
},
}
Product view → ViewContent:
product: {
view: {
name: 'ViewContent',
data: {
map: {
content_ids: { fn: (e) => [e.data.id] },
content_type: { value: 'product' },
content_name: 'data.name',
value: 'data.price',
currency: { value: 'USD' },
},
},
},
}
Order complete → Purchase:
order: {
complete: {
name: 'Purchase',
data: {
map: {
content_ids: { fn: (e) => e.nested?.map((n) => n.data.id) ?? [] },
content_type: { value: 'product' },
value: 'data.total',
currency: 'data.currency',
num_items: { fn: (e) => e.nested?.length ?? 0 },
},
},
},
}
Transform to REST API format:
'*': {
'*': {
name: { fn: (e) => `${e.entity}_${e.action}` }, // page_view
data: {
map: {
eventName: 'name',
eventData: 'data',
userId: 'user.id',
sessionId: 'user.session',
timestamp: 'timestamp',
metadata: {
map: {
consent: 'consent',
globals: 'globals',
},
},
},
},
},
}
Different mapping based on event data:
order: {
complete: [
// High-value orders get extra tracking
{
condition: (e) => (e.data?.total ?? 0) > 500,
name: 'high_value_purchase',
data: {
map: {
value: 'data.total',
priority: { value: 'high' },
notify: { value: true },
},
},
},
// Standard orders
{
name: 'purchase',
data: { map: { value: 'data.total' } },
},
],
}
extend / remove)Some packages (such as @walkeros/transformer-ga4) ship default mapping rules.
Normally a user rule at the same key replaces the default in full. Use extend
or remove to patch instead.
Two layers, two keywords:
extend runs at init (config layer): deep-merges a partial rule onto the
shipped default. A null value clears an inherited field.remove runs after evaluation (output layer): strips dotted paths from
the final data payload. Applied last, always wins.A rule with neither keyword keeps the existing replace behavior.
{
"purchase": {
"extend": {
"data": { "map": { "affiliation": "params.ep.affiliation" } }
},
"remove": ["currency"]
}
}
This keeps all fields the package ships for purchase, adds affiliation, and
strips currency from the output.
For the full reference and the two-layer model, see Mapping.Rule docs.
At any value position, an array of values is a fallback chain: the first entry that resolves to a defined value wins.
{
"item_id": [
{ "key": "data.sku" },
{ "key": "data.id" },
{ "value": "unknown" }
]
}
Use this to try multiple source fields before falling back to a constant.
Only include PII if consent granted:
user: {
login: {
name: 'login',
data: {
map: {
method: 'data.method',
// Only include email if marketing consent
email: {
key: 'user.email',
consent: { marketing: true },
},
// Only include user ID if functional consent
userId: {
key: 'user.id',
consent: { functional: true },
},
},
},
},
}
Catch-all for unmatched events:
// Any product action
product: {
'*': {
name: { fn: (e) => `product_${e.action}` },
data: 'data',
},
}
// Any click on any entity
'*': {
click: {
name: 'element_click',
data: {
map: {
element_type: 'entity',
element_id: 'data.id',
},
},
},
}
Transform HTTP input to walkerOS event:
// In source config
{
mapping: {
// Map incoming field names to walkerOS structure
name: { fn: (input) => `${input.entity} ${input.action}` },
data: 'payload',
user: {
map: {
id: 'userId',
session: 'sessionId',
},
},
},
}
'data.nested.field'e.data?.price ?? 0nested array exists and has itemsReference:
testing
Use when wiring `@walkeros/transformer-ga4` into a server flow, overriding default GA4 event mappings, dropping events, adding custom event keys, or troubleshooting GA4 Measurement Protocol decoding. Covers the `before`-chain wiring contract, configuration recipes, and per-field patching with extend/remove.
testing
Use when writing, simulating, validating, or testing with walkerOS step examples. Covers the complete lifecycle from authoring examples to CI integration.
tools
Use when bundling walkerOS flows, testing events with simulate/push, running local servers, validating configs, or configuring Flow JSON files.
data-ai
Use when working with walkerOS sources, understanding event capture, or learning about the push interface. Covers browser, dataLayer, and server source patterns.