Campaigns & Workflows

How Nuxie campaigns run on‑device: triggers, nodes, timing, goals, and exits

PreviousNext

Campaigns & Workflows (On‑Device)

Campaigns are your container for describing when to show flows and who will see them. They chain together a series of actions, designed visually so you can express targeting and timing clearly—showing the right flow to the right customer at the right moment. Once published, campaigns run entirely on the customer’s device, making them instant, offline‑resilient, and independent of network timing.

Mental model

  • Campaign: the container for who can enter (trigger), how often (frequency), optional goal + exit policy, and a workflow graph of nodes to run.
  • Workflow: a visual sequence of actions we call nodes (show a flow, wait, branch, update data, send an event, end) that runs in order and can branch based on conditions.
  • Journey: a single customer’s path through a campaign over time. The journey persists locally on a user's device, can pause/resume, and records conversion/exit.

Workflows execute on the device. Nodes like Show Flow present UI immediately; nodes like Time Delay or Time Window pause the journey and schedule resume. Goals and exits are continuously evaluated around node execution.

Who enters (triggers)

Triggers are the actions that start the customer's journey in the workflow. We have two:

  • Event trigger: enter when your app records an event with the configured name and an optional property filter.
  • Segment trigger: enter when the customer matches a condition based on segments and/or their attributes.

Notes

  • Event triggers start a journey immediately when matched.
  • Segment membership is evaluated continuously on device and segment triggers start the journey when the customer enters the segment.

Inputs

FieldTypeRequiredDescription
type`"event""segment"`yes
config.eventNamestringwhen type = eventName of the incoming app event that starts the campaign. Examples: app_opened, onboarding_completed.
config.whenconditionoptional (event)A boolean rule over event properties (built in the visual builder). Used to narrow which events qualify.
config.matchconditionwhen type = segmentA boolean rule over segment membership and/or attributes (built in the visual builder). When true, the customer may enter.

How often (frequency policies)

Re‑entry frequency options:

  • once: allow entry if the customer has never completed this campaign. Caution: this mode does not block entry when another journey for this campaign is already live; avoid triggers that can fire repeatedly, or add gating.
  • every_rematch: allow entry whenever the trigger matches and there is no live journey for this campaign.
  • fixed_interval: allow re‑entry only after the configured interval (seconds).
    • If a live journey exists and its age ≥ interval, the system cancels the live journey and starts a new one.
    • If no live journey exists, the system checks the time since the last completion.

Inputs

FieldTypeRequiredDescription
mode`"once""every_rematch""fixed_interval"`
intervalSecondsnumberwhen mode = fixed_intervalMinimum seconds between journey starts. If a live journey is older than this, it is cancelled and restarted on re‑trigger.

Goals and exits

Optional goal snapshot and exit policy are latched at journey start and honored for the life of the journey.

Goal kinds

  • event: conversion occurs if a qualifying event’s timestamp lies within [anchor, anchor + window]. Conversion “latches” at the event time even if evaluation happens later (e.g., offline sync).
  • segment_enter / segment_leave: conversion is true when membership changes as specified during evaluation, and only if still within the window.
  • attribute: a rule over attributes/events/segments that must evaluate to true during evaluation (within the window).

Window and anchor

  • window (seconds): per goal or defaulted by campaign type (e.g., paywall, onboarding).
  • conversion anchor: when the window starts; defaults to workflow_entry.

Exit policy

  • on_goal: exit when the goal is met.
  • on_stop_matching: exit when a segment‑triggered journey no longer matches its trigger condition.
  • on_goal_or_stop: either of the above.
  • never: never exit early; run the whole workflow.

Evaluation timing

  • Goal and exit are evaluated before starting, before each node, after each node, and on relevant events/segment changes. This provides immediate exits after conversion or stop‑matching.

Inputs (Goal)

FieldTypeRequiredDescription
kind`"event""segment_enter""segment_leave"
eventNamestringwhen kind = eventName of the event that counts as a conversion.
segmentstringwhen kind = segment_enter/segment_leaveThe saved segment to observe for enter/leave.
attributeRuleconditionwhen kind = attributeRule over customer attributes/events/segments that must become true to convert.
windowSecondsnumberoptionalConversion window length. Defaults by campaign type (e.g., paywall = 21 days, onboarding = 10 days).
anchor"workflow_entry"optionalWhen the conversion window starts. Defaults to workflow_entry.

Inputs (Exit policy)

FieldTypeRequiredDescription
mode`"on_goal""on_stop_matching""on_goal_or_stop"

Runtime semantics (what actually happens)

High‑level loop:

  1. Trigger matched → create a journey, snapshot goal/exit/window, and set the entry node.
  2. Evaluate goal/exit. If an exit should occur, complete the journey.
  3. Execute the current node and get a result:
    • continue([ids]) → advance to the next node.
    • async(date?) → pause; schedule resume at date (or indefinite when nil).
    • skip(id?) → skip this node; continue at id (or end if nil).
    • complete(reason) → complete journey.
  4. Repeat until async or complete.

Important behaviors

  • Show Flow is fire‑and‑forget: it presents a paywall and the journey continues immediately. Add a Wait Until if you need to branch on purchase/dismiss, or a Time Window to hold subsequent nodes.
  • Wait Until reacts to events and segment changes. Timeout paths only mature on timer/start resumes (not during reactive resumes); reactive resumes clamp rescheduling to avoid tight loops.
  • Time Window checks local device time by default (useUTC: false) or UTC (true). Start == end is treated as “always open.” Overnight windows are supported.
  • Random Branch assigns a cohort using a 0–100 draw; percentages should sum to 100. Each cohort maps to an outgoing edge in the order you define. If configuration and edges are misaligned, routing falls back to a safe default connection.
  • Branch has two outgoing edges: the first edge is taken when the condition is true; the second when false. Multi‑branch has N+1 outgoing edges: the first N align with your conditions in order; the last edge is the default when no condition matches.

Workflow Nodes

Action nodes

Show Flow

Presents a published flow (paywall) in a dedicated window. The journey advances immediately after presentation.

Inputs

FieldTypeRequiredDescription
flowIdstringyesIdentifier of the published flow to present.

Outputs

EdgesDescription
1Continues to the next connected node immediately after presentation.

Update Customer

Sets customer properties on device (merged into the profile) and emits telemetry for observability.

Inputs

FieldTypeRequiredDescription
attributesobject (key → value)yesProperties to set. Values can be string, number, or boolean.

Outputs

EdgesDescription
1Continues after attributes are updated.

Send Event

Emits a synthetic event from the workflow. Useful for analytics breadcrumbs or to trigger other automation.

Inputs

FieldTypeRequiredDescription
eventNamestringyesName of the event to send.
propertiesobjectnoAdditional key/value pairs (string/number/boolean) to include on the event.

Outputs

EdgesDescription
1Continues after the event is recorded.

Call Delegate

Calls into your app with a message and optional payload so you can perform custom actions (e.g., refresh entitlements, navigate).

Inputs

FieldTypeRequiredDescription
messagestringyesA short identifier for the action your app should handle.
payloadobjectnoArbitrary JSON‑serializable data your app can consume.

Outputs

EdgesDescription
1Continues after the delegate call is dispatched.

Timing

Time Delay

Pauses the journey for a fixed duration, then resumes.

Inputs

FieldTypeRequiredDescription
durationSecondsnumberyesHow long to pause before continuing. If ≤ 0, the journey continues immediately.

Outputs

EdgesDescription
1Continues after the delay elapses (or immediately if ≤ 0).

Time Window

Continues only when the current time falls inside the configured window; otherwise the journey pauses until the next open.

Inputs

FieldTypeRequiredDescription
startTimestring (HH:MM)yesStart of the allowed delivery window (time‑of‑day).
endTimestring (HH:MM)yesEnd of the allowed delivery window (time‑of‑day). If equal to startTime, the window is treated as always open.
useUTCbooleanyesWhen true, interpret times in UTC; otherwise use the device’s local timezone.
daysOfWeeknumber[]noValid days using iOS numbering: 1=Sun … 7=Sat. Empty/omitted means every day. Overnight windows are supported.

Outputs

EdgesDescription
1Continues when the window is open; otherwise waits until the next opening.

Wait Until

Waits for the first matching path to become true, or for a path‑specific timeout to mature.

Inputs

FieldTypeRequiredDescription
paths[].idstringyesLabel for the path (used in analytics).
paths[].whenconditionyesRule to check. Evaluated reactively on events/segment changes and on timer resumes.
paths[].timeoutSecondsnumbernoMaximum time to wait for this path before taking it by timeout. Timeouts mature on timer/start resumes (not during reactive resumes).

Outputs

EdgeDescription
one per pathEach defined path maps to an outgoing edge. The first matching path (by rule or by timeout) is taken.

Logic & experiments

Branch (If/Else)

Routes customers down one of two paths.

Inputs

FieldTypeRequiredDescription
conditionconditionyesRule to evaluate.

Outputs

EdgeDescription
firstTaken when the condition is true.
secondTaken when the condition is false.

Multi‑branch

Tries multiple conditions in order and routes to the first match; falls back to the default path.

Inputs

FieldTypeRequiredDescription
conditions[]conditionyesOrdered list of rules. The journey takes the first rule that matches.

Outputs

EdgeDescription
first…NTaken when the corresponding condition (in definition order) is true.
defaultTaken when none of the conditions match.

Random Split (A/B/n)

Splits traffic into named cohorts by percentage.

Inputs

FieldTypeRequiredDescription
branches[].percentagenumber (0–100)yesShare of customers to route to this branch. All branches should sum to 100.
branches[].namestringnoOptional human label for the cohort (e.g., "A", "discount10").

Outputs

EdgeDescription
one per branchEdges align with branches in the order defined. Each cohort maps to its corresponding edge.

Control

Exit

Stops the journey.

Inputs

FieldTypeRequiredDescription
reasonstringnoOptional label recorded in analytics. Accepted values include completed, goal_met, expired, error. Defaults to completed.

Outputs

EdgesDescription
0No outgoing edges; the journey ends.

Automatic Events

These events are emitted automatically so you don’t need to duplicate them. System events use a $ prefix. All events include standard metadata like a timestamp and a session id when available.

  • Lifecycle

    • $app_installed
      • When: first launch on a device.
      • Properties: app_version, install_date, source.
    • $app_updated
      • When: app version changes between launches.
      • Properties: previous_version, app_version, update_date, source.
    • $app_opened
      • When: app enters foreground (also on first launch and after updates).
      • Properties: open_date, app_version, source.
    • $app_backgrounded
      • When: app enters background.
      • Properties: background_date, source.
  • Campaign & Journey

    • $journey_exited
      • When: a journey ends (natural completion, goal met, stop‑matching, expired, cancelled, error).
      • Properties: journey_id, campaign_id, exit_reason (completed|goal_met|trigger_unmatched|expired|cancelled|error), had_conversion (bool), optionally duration_seconds, converted_at, goal_kind.
    • $journey_goal_met
      • When: a journey’s goal criteria are met within the conversion window.
      • Properties: journey_id, campaign_id, goal_kind, met_at, window_seconds.
  • Flows (paywalls)

    • $flow_shown
      • When: a Show Flow node presents a flow.
      • Properties: journey_id, campaign_id, node_id, flow_id.
    • $flow_completed
      • When: a presented flow is closed.
      • Properties: flow_id, journey_id, campaign_id, completion_type (dismissed|purchase|timeout|error), optional products_shown; on errors, an error_message may be included.
  • Workflow nodes (execution telemetry)

    • $node_executed
      • When: any node finishes execution.
      • Properties: journey_id, campaign_id, node_id, node_type, result (continue|async|skip|complete). Depending on result, includes next_nodes, resume_at, skip_to, or exit_reason.
    • $node_branch_taken
      • When: a Branch or Multi‑branch chooses a path.
      • Properties: journey_id, campaign_id, node_id, branch_path (true|false|condition_#|default), condition_result (bool).
    • $node_random_branch_assigned
      • When: a Random Split assigns a cohort.
      • Properties: journey_id, campaign_id, node_id, cohort_name (optional), cohort_value (0–100 draw).
    • $node_wait_completed
      • When: a Wait Until path wins (by condition or timeout).
      • Properties: journey_id, campaign_id, node_id, matched_path, wait_duration_seconds.
    • $node_errored
      • When: a node throws an unrecoverable error.
      • Properties: journey_id, campaign_id, node_id, node_type, error_message.
  • Data & integration helpers

    • $customer_updated
      • When: an Update Customer node sets attributes.
      • Properties: journey_id, campaign_id, node_id, attributes_updated (string array).
    • $event_sent
      • When: a Send Event node emits a custom event.
      • Properties: journey_id, campaign_id, node_id, event_name, event_properties.
    • $delegate_called
      • When: a Call Delegate node signals the host app to perform an action.
      • Properties: journey_id, campaign_id, node_id, message, optional payload.
  • Commerce

    • purchase_completed
      • When: a purchase completes successfully through the built‑in purchase path.
      • Properties: product_id, price, display_price.
    • purchase_failed
      • When: a purchase fails through the built‑in purchase path.
      • Properties: product_id, error.
    • restore_completed
      • When: a restore operation completes and finds prior purchases.
      • Properties: restored_count.
    • restore_failed
      • When: a restore operation fails.
      • Properties: error.
    • restore_no_purchases
      • When: a restore operation finds no prior purchases.

Notes

  • You generally do not need to track these yourself; they are emitted automatically when you use flows, nodes, and the built‑in purchase path.
  • For conversion reporting, many teams use $flow_completed with completion_type = purchase and/or purchase_completed as the success signal.

Conditions (what you can reference)

Conditions are boolean rules you build in the visual editor. You can:

  • Check customer attributes (country, plan, install date, etc.).
  • Reference event properties and frequencies.
  • Test membership in your saved segments.

Worked examples

Example A: “Greet new customers with a paywall, but only during daytime”

  • Trigger: segment → matches is_new_customer.
  • Frequency: every_rematch.
  • Goal: event purchase_completed, window 21 days.
  • Exit: on_goal_or_stop (stop if they leave is_new_user).
  • Workflow: time_window → show_flow → wait_until (purchase or 24h timeout) → exit.

Example B: “Winback after a dismiss if no purchase in 7 days”

  • Trigger: event viewed_paywall.
  • Frequency: fixed_interval 14 days (cancels/refreshes if you trigger again after 14 days).
  • Goal: event purchase_completed, window 14 days.
  • Exit: on_goal.
  • Workflow: show_flow → wait_until (purchase path or 7‑day timeout) → branch on country → show variant flow → exit.

Practical tips

  • Show Flow does not block; add Wait Until if subsequent logic depends on outcomes.
  • For “once” campaigns, prevent duplicate live journeys by gating the trigger (e.g., additional segment condition) when multiple events may arrive quickly.
  • Time Window uses iOS weekday numbering (1=Sun … 7=Sat); start==end means always open; overnight windows are supported.
  • Multi‑branch uses the last path as the default and as the error fallback.
  • Random splits should total 100; otherwise the system falls back to a safe default connection.
  • Call Delegate lets you integrate app‑specific actions without changing your app integration.

If you want a deeper API reference for individual node fields, see Reference → Workflow Nodes.