NavonaAI logoNavonaAI

product

What a Cart Abandonment Model Actually Sees

A storefront emits a huge volume of behavioral data. Here's why pattern recognition beats a fixed rule — and what we deliberately don't collect.

NavonaAI Team6 min read

We don't publish the exact signals or thresholds our model uses to decide when to intervene — that's on purpose, for the same reason a spam filter doesn't publish its exact rules. But we can talk honestly about the shape of the problem, and about what the model is built on.

A storefront produces more data than a single rule can use

Every session on a Shopify storefront running Navona generates a stream of client-side and web-pixel events — page views, product interactions, cart changes, navigation patterns, and more — each carrying a number of fields describing the moment it happened. Multiply that across a session, and a single shopper's visit isn't one data point. It's a sequence of many, each with its own context.

A fixed-rule script can only look at a handful of those signals at a time, combined with hand-picked thresholds: if this happens, and this hasn't happened, and it's been this long, trigger. That's a reasonable way to build a first version, and it works. But it has a ceiling. The rule doesn't get better with more traffic — it does the same thing on day one and on day one thousand, and every edge case it misses has to be found by a human and hand-coded in as a new branch.

Pattern recognition over the whole surface is a different tool

A model trained across that same event surface isn't limited to a handful of hand-picked signals evaluated one at a time. It can weigh many fields against each other simultaneously, and its read on what a given pattern means improves as more sessions accumulate. Where a fixed rule plateaus the day it ships, a model has a mechanism to keep improving — that's the actual argument for building one, independent of any specific signal it happens to weigh today.

We're deliberately not going to describe which signals matter most or how they're combined. That's true of the fixed-rule approach too, for the same reason: publishing the exact conditions that trigger an intervention would let anyone reverse-engineer around them, which defeats the point of having them at all.

The same behavior means different things on different stores

A pause in the middle of a session is not the same signal on a €30 impulse-purchase store as it is on a €300 considered-purchase store. On the cheaper store it might already indicate real hesitation; on the pricier one, the same pause might be completely normal deliberation while a shopper compares options. A single fixed threshold applied uniformly across stores gets this wrong in one direction or the other on any store that isn't close to average. A model that learns store-specific patterns, rather than applying one global rule everywhere, is built to account for exactly this kind of variance — store to store, and category to category within a store.

This is also why a signal ranking wouldn't be an honest thing to publish even if we wanted to: "signal X matters most" is only ever true in aggregate, and the entire point of the model is that it doesn't apply the same weighting everywhere.

What the model doesn't need

The strongest trust signal here isn't about what we collect — it's about what we don't. The intervention doesn't require an email address or a phone number to work. It reads and reacts to on-page shopping behavior in the moment, which means we're not asking a shopper to hand over contact information before we can do the job. If a tool you're comparing wants an email address to power its logic, that's a design choice, not a technical necessity — behavioral intervention doesn't need it.

What we'll say, and what we won't

We'll talk about the shape of the data, the reasoning for using a model instead of a fixed rule, and why one signal can't be ranked as universally more important than another. We won't publish the specific signals, the thresholds, or the timing our model uses to decide when to act. That's the same instinct behind being explicit that our own attribution numbers are attribution, not lift — see Attribution Is Not the Same as Lift.

Appendix: the event catalog, in full

"A large surface" is a claim that should be checkable. Here is every event type NavonaAI's storefront integration produces, current as of 26 Aug 2026. One field is deliberately incomplete, and we say exactly which one and why, rather than pretend the appendix is unabridged.

Storefront events (Shopify's own web-pixel taxonomy)

These are Shopify's standard pixel event types — not proprietary to Navona, and the same events any pixel-based analytics tool on the platform receives. Every event carries a common envelope (id, name, timestamp, clientId) plus an event-specific payload.

EventPayload
product_added_to_cartShopify's standard cart-line payload, forwarded unmodified
product_removed_from_cartShopify's standard cart-line payload, forwarded unmodified
product_viewedShopify's standard product payload, forwarded unmodified
collection_viewedcollection.id, collection.title
search_submittedsearchResult.query, matched product/variant IDs
checkout_startedbuyerAcceptsEmailMarketing, buyerAcceptsSmsMarketing, attributes, token, currencyCode, discountApplications, discountsAmount, email, phone, lineItems (variant ID + discount allocations), order, delivery
checkout_completedSame shape as checkout_started
checkout_contact_info_submittednone — fires with no payload
checkout_address_info_submittednone — fires with no payload
checkout_shipping_info_submittednone — fires with no payload
payment_info_submittednone — fires with no payload
cart_viewednone — fires with an empty payload
page_viewednone — fires with no payload
alert_displayedShopify's standard alert payload, forwarded unmodified
ui_extension_erroredthe error object

email and phone above are Shopify's own standard checkout fields, present because a checkout inherently has them once a shopper reaches that step — not something we ask for. The intervention itself, covered above, never requires either.

Navona's own prevention events

Session- and outcome-level events our own script emits, independent of the pixel above. Every one carries storeId, sessionId, clientId, cartId, and an optional occurredAt.

EventWhat it marks
session_started, cart_createdsession and cart lifecycle
popup_shown, popup_reshownthe offer rendered
popup_accepted, popup_rejectedthe shopper's response
popup_copy_failed, popup_delivery_failedreliability telemetry — the offer didn't reach the shopper cleanly
chatbot_accepted, chatbot_rejected, objection_accepted, objection_rejected, user_engaged, user_messagedthe objection-handling conversation, where offered
new_abandoning, repeat_abandoning, abandonment_detectedabandonment classification, first-time vs. repeat

popup_shown and popup_accepted also carry a discountCode and a trigger field. We're not publishing the trigger field's values here — they're the specific behavioral classification a signal-level ranking post would have exposed, which is the same thing this post already said we wouldn't do. A small number of additional internal telemetry events exist and aren't individually listed, for the same reason.

Frequently asked questions