FLOWLOGIC
module /automation-engine-core

unit U33 of 4

Data mapping & expressions

step data, {{ }} references, transforms

In a flow, each step’s output becomes available to every step below it. You wire data together with expressions — the `{{ }}` syntax — that reference a prior step’s output by its path, like `{{ trigger.body.email }}` or `{{ step_2.id }}`. The “Data to Insert” panel shows exactly what each step produced (after you test it), so you pick real fields instead of guessing. Mapping is the quiet cause of most “why is this field empty” bugs: a mistyped path resolves to nothing rather than an error.

Build your clean, downstream-ready shape explicitly rather than forwarding the raw trigger data everywhere. Reference the exact step + path; when a value might be missing, give it a fallback so one odd record doesn’t poison the write. For anything the built-in expressions can’t do — reshaping arrays, hashing, conditional logic — drop in a Code Piece, which receives its `inputs` as a typed object and returns a value the next step can use.

Where it breaks: assuming a field always exists. `{{ trigger.body.customer.email }}` yields nothing the moment one payload nests it differently, and that empty value flows silently into a CRM or email step. Test every step to see the true shape, guard optional fields, and validate before anything irreversible.

worked example

A Code Piece projecting a clean, minimal record from a messy trigger payload.

// Code Piece — inputs are the expressions you mapped in from earlier steps
export const code = async (inputs) => {
  const lead = inputs.payload;                 // mapped from {{ trigger.body }}
  return {
    email: lead?.contact?.email ?? null,
    fullName: [lead?.first, lead?.last].filter(Boolean).join(' '),
    source: lead?.utm?.source ?? 'direct',
    dealSize: Number(lead?.value ?? 0),
  };
};

field checklist

common failure — Empty field written downstream

A mapping used `{{ trigger.body.customer.email }}` assuming every payload had a customer object; one variant nested it differently, so the expression resolved to nothing and the CRM step created records with blank emails that broke dedup. Test the trigger to see the real shape, add a fallback, and route records missing required fields to a review branch instead of writing them.

check your understanding

This mapping must not throw when a payload nests the contact differently, and must fall back to null rather than an empty value. Which operator belongs in the blank?

email: lead?.contact?.emailnull,

next unit opens once this is passed

sandbox validation

The check above confirms you followed the unit. Marking the module COMPLETED takes more: build the automation in your own engine and submit the exported flow and its run evidence, signed, to your unique validation URL. See the module page for that spec.