Data Mapping, Arrays & Iterators
Building a scenario is mostly one activity: telling each module which data to use. That's mapping. Master mapping and the lists-of-things problem, and there's almost nothing in Make you can't build.
Mapping a single field
When you open a module - say "Create a Trello card" - its fields are blank. Click into a field and Make drops down a panel showing every field from every earlier module, grouped by module. You click email from the trigger, and a colored token appears in the field. That token is a reference: "put the email value from step 1 here, at run time."
You can mix tokens with literal text. A subject line might read:
New signup: {{name}} ({{email}})
Each {{...}} is a mapped token; the rest is typed. At run time Make substitutes the real values. If name is empty for a given bundle, the token resolves to nothing - Make doesn't error, it leaves a gap. That silent emptiness is a frequent source of "why is my message blank" confusion, so check your test runs.
Functions: reshaping values inline
Often the raw value isn't in the shape the next app wants. The mapping panel has a second tab full of functions - small transformations you wrap around a token.
A few you'll reach for constantly:
upper(name) → "ADA LOVELACE"
formatDate(signed_up; "MMMM D, YYYY") → "June 30, 2026"
trim(notes) → strips leading/trailing spaces
if(amount > 1000; "big"; "small") → conditional value
substring(phone; 0; 3) → first three characters
Functions nest, so you can upper(trim(name)). The big three categories are text (case, trim, split, replace), date/time (parse and format - and dates are where most beginners get stuck, because a string from one app rarely matches what the next app expects), and math/logic (if, comparisons, rounding). You don't memorize these; you open the functions tab and skim.
Routers: sending bundles down different paths
A router is a module that splits the flow into branches. Each branch can have a filter - a condition on the line. The bundle takes every branch whose filter passes.
flowchart LR
T[New order] --> R{Router}
R -->|amount > 1000| S[Notify sales]
R -->|amount <= 1000| L[Just log it]
Filters are how you say "only continue if." You set them by clicking the wrench on the line between two modules. A filter that fails stops that bundle on that path - quietly, not as an error. Routers are Make's answer to "if this, do that; otherwise do this other thing," and they're far cleaner than the bolt-on branching in checklist tools.
The list problem: arrays
Real data is full of lists. An invoice has many line items. An API returns many search results. A single bundle field can itself hold an array - a list of items, each with its own fields.
Here's the catch: a normal module processes one item. If you map an array directly into "Create a row," you'll get unpredictable behavior, because the module expected one value and got a list. Make gives you two tools for the gap between "one thing" and "many things," and knowing which to use is the core skill of this phase.
Iterator: split one bundle into many
An Iterator takes an array and breaks it into separate bundles - one per item. Feed it an array of three line items, and every module after the iterator runs three times, once per item.
Before iterator: 1 bundle { items: [A, B, C] }
After iterator: 3 bundles {A} {B} {C}
Use an iterator when you have a list and want to do something with each item - create a row per line item, send a message per recipient.
Array Aggregator: collapse many bundles into one
The Array Aggregator is the mirror image. It takes many bundles and merges them back into a single bundle holding one array.
Before aggregator: 3 bundles {A} {B} {C}
After aggregator: 1 bundle { collected: [A, B, C] }
Use an aggregator when downstream you want one of something built from many - one summary email listing all items, one API call with all records attached. There's also a Text Aggregator for stitching many bundles into one block of text (great for "build a list and put it in one message").
The classic pattern is the pair: iterator → process each → aggregator. Split a list apart, do work on each piece, then gather the results back into one. When a scenario "runs too many times" or "only does the last item," the fix is almost always a missing or misplaced iterator/aggregator.
flowchart LR
A[Get invoice] --> B[Iterator: line items]
B --> C[Lookup product]
C --> D[Array aggregator]
D --> E[One summary record]
A worked picture
Say a webhook delivers an order with three line items, and you want one Slack message summarizing them, but only for orders over $50.
- Webhook receives the order → verify: bundle shows the
itemsarray. - Filter on the line:
total > 50→ verify: small orders stop here. - Iterator over
items→ verify: downstream runs once per item. - (Optional lookup per item) → verify: each item gets enriched.
- Text Aggregator joins items into one block → verify: one bundle out.
- Slack module sends the joined text → verify: one message, all items listed.
Notice the rhythm: split, work, gather. Once that pattern is in your hands, the rest of Make is picking the right module and mapping the right field. The next phase covers what happens when a step fails mid-run - and the operations cost that all this iterating quietly racks up.