Skip to content
Ayra Docs

Journey Guard rules

Journey Guard is the gate every outbound action passes through before it reaches a customer. It applies four kinds of rule in order (frequency caps, quiet hours, channel limits, conflict resolution), can decide that nothing should be sent (NO_ACTION), and writes the reason for every send, hold and drop to the customer’s timeline. Flows, module messages and engine actions all go through it; there is no way for a message to skip it.

Every outbound action passes through Journey Guard, which enforces frequency caps, quiet hours and channel limits, and resolves conflicts between modules. 'Do nothing' is a valid outcome.

Example A win-back offer and a referral nudge both qualify on Tuesday. One is sent, the other is scheduled, and the timeline says why. See it on How it works

Caps limit how many actions a customer can receive in a window. They are set per store and can be overridden per flow (tighter only, never looser).

CapDefaultApplies to
Promotional sends per customer1 per 7 daysOffers, bonuses, referral nudges, win-backs
Transactional sends per customerNo capOrder, shipping, restock you asked for, points statements
Review requests per customer1 per 30 days, and once per orderReview module
Restock alerts per variant per customer1 per restock eventBack in Stock
Total sends per customer per day2Everything except transactional

When a cap blocks an action, the action is held and rescheduled for the first window where it fits, unless it has expired by then (opportunities carry an expiry), in which case it is dropped.

No promotional send goes out between the quiet hours you set (default 21:00–08:00 in the store’s time zone, or the customer’s time zone when Ayra knows it from their last order address). Transactional messages ignore quiet hours. An action that lands in quiet hours is held until they end.

Each channel has its own cap and consent requirement. SMS and WhatsApp need explicit consent and are capped at 1 promotional send per 14 days by default; push follows the Shop app’s own limits; email follows the store cap. A customer’s preferred channel (the one they last engaged with) is used when the action allows more than one. If the preferred channel is capped or has no consent, Journey Guard falls back to the next allowed channel rather than waiting, unless the flow says “this channel only”.

When more than one module or flow wants to reach the same customer in the same window, Journey Guard picks one. The rules:

  1. Higher opportunity priority wins (P0 to P4). A VIP restock alert (P1) beats a referral nudge (P3).
  2. Ties go to the action with the earlier expiry.
  3. Incentive Guard applies: an action that would stack a discount on an incentive the customer already holds is dropped, not held.
  4. Trust Recovery applies: review requests and promotions are held while the customer has an open support issue, and released three days after it is resolved.
  5. The losing action is held and rescheduled after the cap window, or dropped if it expires first.

NO_ACTION is a valid outcome of a decision, not an error. The engine records it when every eligible action was blocked by a rule, when the best action’s expected value is below the threshold you set, or when the customer is in a state where nothing should happen (open issue, recent refund, unsubscribed). Each NO_ACTION carries the rule that produced it, so “why didn’t Ayra send anything” has a one-line answer on the timeline.

Every action line in a customer’s timeline has a status and a reason. The reason is a short code followed by the rule’s values at the time of the decision.

StatusReason formatExample
Sentrule: <name>rule: earn reminder, points expiring in 14 days
Sentopportunity: <type> P<n>opportunity: VIP_RESTOCK P1, via whatsapp (preferred)
Heldcap: <cap> (<used>/<limit> in <window>)cap: promotional (1/1 in 7d), rescheduled 2026-10-21
Heldquiet hours: <from>–<to> <tz>quiet hours: 21:00–08:00 Asia/Karachi, rescheduled 08:00
Heldconflict: lost to <action> (P<n>)conflict: lost to VIP_RESTOCK (P1), rescheduled 2026-10-21
Heldtrust recovery: ticket #<id> opentrust recovery: ticket #4412 open, release +3d after close
Droppedexpired: <opportunity> after <n>hexpired: WIN_BACK after 72h, never fit a window
Droppedincentive guard: <existing incentive>incentive guard: 15% welcome code active until 2026-10-20
No actionNO_ACTION: <rule>NO_ACTION: below value threshold (score 0.12 < 0.25)

Filter the timeline by status to review every hold and drop for a customer, and use the Journey Guard report in Analytics to see the same counts across all customers.

Caps, quiet hours and channel limits are in Ayra → Journey Guard. Changes apply to decisions made after you save; held actions are re-evaluated at their next scheduled time under the new rules. A flow can set tighter caps for its own sends but cannot loosen the store caps. Priorities for opportunity types are in Opportunities → Types.

Something missing or wrong on this page? Ask us and we will fix the docs.