Where the decision starts

Immediately after payment, a customer receives “you still have items in your cart.” They wonder whether the order failed, while the CRM owner asks why a buyer-exclusion rule did not stop the message. This is a design example illustrating an incorrect-send mechanism.

First distinguish eligibility to enter a Journey from eligibility to receive a message now. Being a nonbuyer when creating a cart does not imply remaining one after a wait. Investigate delayed purchase propagation, mismatched customer/business references and duplicate events restarting a Journey separately. OneSignal permits concurrent entry in event-based Journeys, while Shopify does not guarantee webhook order. A setting named “exclude buyers” does not resolve these conditions by itself.[1][5]

Start by defining purchase completion, which cart reminder ends and when state is checked again. Then connect platform exits/branches to the application's sending decision. However, a last-minute query does not make the external order and messaging systems commit as one transaction. Define where prevention remains possible and where transmission may already have occurred.

Purchase completion and the time to stop a reminder can differ

In Shopify Classic Webhooks, orders/create means order creation and orders/paid means an order was paid. Current financial states separately include PENDING, AUTHORIZED and PAID. PAID includes automatic/manual capture and orders an administrator marked paid. A payment-button click or order creation alone is not evidence that funds processing completed.[3][4]

Yet cart reminders need not continue until payment completion. Telling someone “you have not purchased” can be inappropriate even while their accepted order is still being paid.

This design example chooses the following policy for logged-in customers placing prepaid online orders. Adjust it to actual payment methods and customer-service policy; it is not default Shopify or OneSignal behavior.

  • Hold reminders once an order is created from that cart or payment is in progress. End existing reminders for that cart when purchase completion is confirmed.
  • Hold if order/customer/cart relationships or current state cannot be verified; do not classify uncertainty as nonpurchase.
  • Do not revive an ended cart reminder after cancellation, partial refund or full refund. Evaluate new carts and repurchase campaigns separately.

Shopify also distinguishes orders/cancelled from refunds/create. In particular, refunds/create concerns creation of a refund record independently of actual funds movement. It provides no basis for interpreting the customer as a nonbuyer again or newly eligible for advertising.[3]

Record the decision unit. Customer U purchasing cart C1 does not mean their new cart C2 is complete. Use the service's customer–cart–order relationship, rather than one customer-level purchased=true/false, to determine which reminder ended. Where mapping is impossible, hold that customer's reminders instead of guessing.

How the service works

Messages connected to customer behavior — Use lifecycle stages and behavior to connect channels and timing, then refine journeys through experiments.

Sending can occur between purchase and CRM propagation

The following hypothetical timeline schedules a decision on cart C1 at 10:30. It is neither measured latency nor a product processing guarantee.

TimeEventDistinction to retain
10:00:00Create C1 reminder candidate and begin waitingEntry reason and cart identifier
10:29:58Order source records C1's completed purchaseBusiness-event occurrence time
10:30:00Sending job runs before purchase appears in CRMDecision time and state version read
10:30:01Messaging provider accepts a request allowed by stale state and begins transmissionAcceptance/transmission times and message ID
10:30:02Purchase webhook reaches the applicationWebhook receipt time
10:30:03Application saves C1 as excludedInternal eligibility update time
10:30:05Exit state/event reaches the messaging platformPlatform propagation and evidence of actual Journey exit

Exiting the Journey on the last line does not undo an earlier transmission. OneSignal's Cancel message API stops scheduled or ongoing sends, but explicitly notes that cancellation after sending starts may not prevent all recipients from receiving it.[10]

If the 10:30 job reread the order source and saw the purchase, it could avoid creating the request. A smaller race remains if purchase occurs after that query but just before handoff to the provider. One extra query does not establish zero post-purchase incorrect sends.

Keep purchase occurrence, webhook receipt, internal update and platform update as separate times. Check source timestamp semantics and clock differences; leave unavailable times unknown. These fields are not automatically present in every platform's logs. Distinguish existing evidence from additional instrumentation.

What to configure in OneSignal and what to decide separately

Official documentation checked on September 26, 2026 describes the following controls. Focus on the data each control reads and where it applies, rather than its name.

Required controlOfficial feature and scopeWork remaining in application/operations policy
Entry, exit and reentryEnter through a segment or Custom Event. General Re-entry rules apply to segment Journeys; event Journeys allow reentry.[1]Distinguish duplicate entry for one event from legitimate entry for a new cart
Reevaluate after waitingWait delays time; Wait Until waits for a condition; Yes/No branches on segment membership or message behavior.[2]Elapsed time is not evidence of nonpurchase; define the timeout path
Match completion to the same business itemEvent-triggered Wait Until provides Event Matching between starting and waiting-event properties.[2]Connect values so C1 completion does not end C2's reminder; do not assume every Exit rule provides per-item matching
Conflicts with other JourneysTags/exclusion segments can coordinate membership.[1][2]Do not treat tags read concurrently by several Journeys as an atomic lock

Sources: OneSignal Journey settings and Journey actions.[1][2]

Specifically test already-purchased customers satisfying both entry and exit conditions. OneSignal notes that the first step can execute before exit and recommends an initial wait or explicit exclusions for segment entry. Do not assume event and segment entry can be combined in the same entry rule.[1]

The official abandoned-cart tutorial uses cart_updated for both entry and exit to restart with current cart contents. Reentry filters and empty-cart handling must still be correct. This pattern alone does not resolve an old cart update arriving after purchase.[12]

For strict exclusions, decide where the sending request is created

If the problem is an incorrect purchase exit, first step or identifier mapping in an existing Journey, correct that configuration first. Not every service needs a separate sending system.

When orders span several systems or events repeatedly arrive late, and some valid sends may be sacrificed to reduce incorrect reminders, consider application ownership of the final sending request. The following is a proposed implementation direction.

Candidate → authoritative order source or verified current state → customer/cart mapping → consent/subscription/deduplication/frequency checks → authorization record → messaging API request

Exclude in-progress or completed orders; hold failed queries or unclear mappings. Record decision time, evidence state, campaign configuration version, selected channel and recipient. Reevaluate jobs that waited in a queue before execution. If this stage moves into the application, assign one sending owner so the existing Journey message step does not independently send.

Test two jobs simultaneously reading “not sent yet.” Use uniqueness constraints and transactions to check and reserve sending rights for the customer/cart/reminder step atomically. Retries reuse the existing authorization record and request key rather than creating new ones. This coordinates your own sending jobs; it does not lock purchases in an external order system.

Adding a Journey webhook before a message does not complete this design. Its documented function sends an HTTP request to an external server. Documentation does not establish atomicity between its response, the next message step and the order source. Journey webhooks also have separate access conditions. The gate described here is a separate design using an application queue/scheduler and messaging API, not an automatic Journey property.[13]

The race between the final query and external transmission remains. Detect payment in progress earlier, reduce queue delays and decline to send when state is uncertain to reduce it. Without one transaction spanning external Shopify and OneSignal, do not promise to prevent every receipt after actual purchase time. Operational rules should state both that no request is created when the final check confirms purchase and that already-handed-off requests may not be fully cancelable.

How the service works

Connect the data each campaign needs — Define events and attributes from campaign needs, then align identifiers, transmission timing and measurement tools.

Deduplication, frequency caps and identity are separate problems

Shopify webhooks may arrive out of order or more than once, and delivery is not always assured. Official guidance recommends periodic source reconciliation to recover missing events. Prevent a late “cart exists” event from reversing a confirmed purchase exit, and recover missing purchases through source queries.[5][6]

Deduplicate receipt and sending separately. Shopify X-Shopify-Webhook-Id identifies duplicate deliveries; X-Shopify-Event-Id connects deliveries from the same shop action. Separately retain sending records for the customer/cart/reminder step. Event deduplication alone does not prevent another Journey from creating a message for the same purpose.[6]

Retry the OneSignal messaging API with the same logical request's idempotency_key. Notification creation keys are retained for 30 days. Custom Events deduplication is instead best effort within four hours, not permanent strict event deduplication. Neither mechanism decides whether sending to this customer is appropriate now.[7][8]

Frequency capping reduces overmessaging. OneSignal's feature applies to push, not one combined limit across email, SMS and in-app messages. Capped pushes are discarded rather than queued for later sending. Design purchase eligibility and cross-channel priorities separately.[9]

For one customer across devices, base eligibility on the service customer ID, but one sending decision and receipt on one device are different conditions. Sending to only one device also requires a recipient-selection rule. Check logout on shared devices: OneSignal mobile SDK logout() detaches the current mobile subscription from its user without logging out all other subscriptions.[11]

Do not assume logout removes exposure from notifications already handed off. Avoid unnecessary purchase data on lock screens and recheck the currently logged-in account's cart authorization when opening a notification link. Check channel subscriptions and service-managed marketing consent independently. Do not automatically route around an opt-out through another channel.

Test conditions that must not send before the normal path

This matrix is the chosen policy of the hypothetical service, not platform guarantees or completed test results. The service permits one active cart reminder and one reminder step per customer, using a preselected allowed channel/recipient. A new cart becomes a candidate only after checking the previous reminder's end and the separately defined sending cap.

Exception/inputExpected behavior in this exampleMain ownerEvidence
Normal nonbuyer; valid consent/recipientRequest only one reminder that passes the final checkCRM/sending developmentAuthorization reason, cart ID, send record/message ID
Already purchased at entryExit/exclude without creating the first messageCRM/QAFirst step, exclusion path and no-request record
Late purchase webhook; source query shows purchaseExclude at final sending gateOrder integration/sending developmentQuery result/time and exclusion reason
Purchase event received twiceApply one purchase transition; do not recreate reminderData integrationDelivery-deduplication IDs and processing record
Old cart event after purchaseDo not revert ended C1 to nonpurchaseData integrationEvent time/version and rejected reverse transition
Purchase before final query / racing after itExclude the former; distinguish handoff and record residual risk for the latterSending development/operationsQuery/request/purchase times; cancellation attempt/result
Two Journeys request the same reminder concurrentlyAllow one via shared application sending recordCRM/sending developmentRejected duplicate reservation and chosen campaign
Same customer across devices/profilesDeduplicate by customer and use selected recipient; hold unclear mappingsIdentity integrationCustomer/profile/subscription mapping and selection record
A logs out and B logs in on shared deviceExclude device from subsequent A candidates; block A-data access from old linksApp development/QAUser switch, subscription mapping and link authorization
Opt-out while waitingExclude if reflected in final decision; separately trace handed-off requestsCRM/app developmentConsent/subscription change time, exclusions and residual sends
Cancellation/partial/full refundDo not resume the previous cart reminderCRM/order operationsMaintained exit and any new-campaign approval
State-query failure/missing purchase eventHold pending verification; recover through source reconciliation; do not count as normal nonbuyerIntegration operationsHold reason, reconciliation work and unverified count

Run actual tests on owned or authorized test shops, accounts and devices. Intentionally delay purchase events in the queue or resend one test event and compare with the normal path. No request created, no platform transmission and no device display are different verification results.

Record actual data, observations and retests in the CRM campaign QA scenarios and results workbook. Use the OneSignal customer Journey design workbook when agreeing entry, exit and reentry policy first.

One question before the next send

Choose one live cart reminder and ask the following.

“If this customer purchased, which record stops this send, and at what time?”

If the answer stops at “a segment excludes buyers,” trace when that segment updates, which customer/cart it refers to and how it affects already-waiting messages. Correct missing configuration in the existing tools. For data delays or conflicting sending paths, development, CRM and QA should assess the same timeline.

Reducing incorrect post-purchase sends requires clear exit policy, verifiable state and evidence that sending did not occur, rather than more Journeys.

When Journey design, implementation and verification responsibilities need to be agreed together, IXC CRM marketing automation describes the support scope.