Lifecycle
Nothing sends until a person activates a flow. Only owners and admins can.
Steps
A flow’s steps are a pattern over one user’s events. Each user moves through the steps on their own. When they reach the end, the flow sends.await - wait for an event
await - wait for an event
The user does something. Optional fields:
where: conditions the event must meetwithinSeconds: a deadline. If the event hasn’t happened by then, the user leaves the flow.afterSeconds: the event only counts once this much time has passedbind: save values from the event for later steps or for the message
await: a flow starts when something happens.absent - wait for an event not to happen
absent - wait for an event not to happen
The user does not do something for
forSeconds. This is how you write
“hasn’t opened the app in 3 days”. The clock starts when the user reaches
this step.wait - let time pass
wait - let time pass
Pause for
forSeconds. This is how you write “2 hours after”.Example
“A user added their first connection, then added none for 48 hours”:maxRunAgeSeconds is the longest a user can sit part-way through the flow
before they’re dropped. Set it well above the total of the steps’ windows.
Branches
Steps can also branch. Give a step anext list of the step ids that may
follow it. The first one satisfied wins. Each branch ends on a send step with
its own message. Without next on any step, steps simply run in order.
Conditions
Awhere list holds conditions on the event’s properties. All of them must be
true.
property can be a dotted path into nested properties, like metadata.tier.
To compare against a value saved by an earlier step, use valueRef instead of
value, for example “the same order_id as the cart event”.
Messages
{{ path }}, and can read:
A send whose variable is missing is skipped, not sent with a blank. “Nice
work, !” is worse than no push. The skip is logged with its reason.
Custom data
data holds keys and values for your app’s own code, like which screen to
refresh. It is delivered with the push but never shown to the user. Leave it
out, or set it to null, when the message has none.
Read it in your app.
- Values are text and can use variables, the same as the copy. A value whose variable is missing skips the send, like any other field.
- At most 20 keys per message. A value is at most 256 characters.
- A key is letters, digits and underscores, starts with a letter or underscore, and is at most 64 characters.
aps,pnaianddeep_linkare used by the push itself, so they can’t be keys.
message_too_large.
When it’s filled in
The message is filled in when the flow decides to send. A send delayed by quiet hours still goes out with the copy and data from the moment it was decided, even if you edit the flow in between.Copy tests
Give a send up to 5 message variants. Each send picks one at random and records which, and the flow page compares how each one does. Keep a variant’skey when you reword it, so its history stays attached.
Limits
Every cancelled send is recorded with its reason, so you can see what a flow
would have done. See Debug a user.
When flows compete
If one event completes several flows for the same user, the flow with the highestpriority sends and the others are recorded as suppressed. Priority
defaults to 0.
If a user is already part-way through a flow and its first step matches again,
onOverlap decides: ignore (the default) keeps the run they’re in, and
restart starts them over.