Cart recovery and payment assist
Two optional features that send shopper data to Conviro. Both are off by default and, from 1.4.0, each needs an explicit confirmation from you in addition to its switch. Plan open decision 5, answered as "hold until the merchant confirms" (09cfe93b). Code: AiChat/Observer/{CartSave,CheckoutStarted,PaymentFailure}.php, AiChat/Model/Config.php, AiChat/Setup/Patch/Data/HoldCartEventsUntilConfirmed.php, backend abandoned-cart.service.ts, cart-recovery-email-i18n.ts, commerce-attribution/payment-assist.service.ts, magento-event-ingest.service.ts. Updated 2026-09-25 for release gate R3 (ceaaac4d, ee07b4fc, 8791cdc4): payment assist is real, the recovery e-mail is localized and links to your own cart page.
Switching them on
Either:
- Setup wizard, step 5: tick Quotes / abandoned carts and/or Failed payments. Ticking is the confirmation and switches the feature on at default scope; unticking switches it off, withdraws the confirmation and clears website-level overrides left from 1.3.x.
- Configuration page, Sync Settings: set Abandoned Cart Recovery / Payment Failure Assistance = Yes (default or per website) and Confirm cart data sharing / Confirm payment-failure data sharing = Yes (default scope only), then Save Config (which also tells Conviro — see Reconnect and disconnect).
A switch that is on without its confirmation sends nothing, and the Integration Health card shows a Cart & payment events Warning. Conviro's side follows the same pair: the cartRecovery / paymentAssist capabilities are the default-scope switch and its confirmation, sent with every registration.
What is sent
| Feature | Event | Data | When |
|---|---|---|---|
| Abandoned Cart Recovery | cart.updated | cart (quote) id, shopper e-mail, item count, grand total, currency, up to 10 items (name, SKU, quantity, price), the cart link (cartUrl) | Magento saves the storefront cart (checkout_cart_save_after) for a cart with an e-mail and at least one item, in a selected store view. |
| Abandoned Cart Recovery | checkout.started | quote id, item count, total, currency, the e-mail only when already given, attribution ids | The shopper opens the checkout page; once per checkout state. Recorded only — never a message to the shopper. |
| Payment Failure Assistance | payment.failed | cart id, shopper e-mail, payment method code, grand total, currency, a short error text (tags stripped, ≤ 300 characters), and — from a storefront request, with Revenue attribution on and the shopper's cookie consent where required — the chat visitor id and followed link ids. Never card data. | Order placement fails (sales_model_service_quote_submit_failure). |
In practice a cart has an e-mail when the shopper is logged in; whether a guest cart carries one depends on the checkout (not tested). Carts changed only through REST/GraphQL cart APIs (some headless storefronts) do not fire the Magento event the module listens to.
What Conviro does with it
Cart recovery
If the workspace's cart-recovery capability is on and the cart is worth at least 1:
- The cart is stored (
magento_abandoned_carts: e-mail, cart id, item count, total, currency, items, the store view, its locale and the cart link) and a contact is found or created for the e-mail. - One recovery e-mail per cart is scheduled 60 minutes after the last change to the cart — every cart event pushes it back, so nobody is e-mailed mid-checkout.
- An
order.placedfor the same e-mail cancels it; switching the capability off cancels it at send time; Disconnect cancels every scheduled one; acustomer.deletedfor the e-mail deletes it. - Conviro's cron (every 5 minutes) sends due e-mails; a failed send is retried after 15 minutes, up to 3 attempts.
Language. The store view's locale from the store-view mapping the module sent in the setup wizard (else the event's own store.locale); if that is not a language Conviro ships, the language of the shopper's latest Conviro conversation (found by the cart's contact, a lead or the e-mail the conversation identified or captured, last 90 days); else English. Shipped: every language the chat answers in — en, tr, de, fr, es, it, pt, nl, pl, lt, et, ru, uk, ar, el, he, hi, th, ja, ko, zh (cart-recovery-email-i18n.ts, held to that set by the canned-copy coverage test). The subject, heading, button, note and plain-text body are translated; item names are shown as the store sent them (HTML-escaped).
Link. The button opens the cart link the module sent: the Cart page URL (headless stores) you set for the store view (Sync Settings, store view scope — for a PWA / headless storefront), otherwise the store view's own checkout/cart URL (with its store code / domain). Without either (a cart from a module before 1.4.0) it falls back to the store view's base URL from the mapping + /checkout/cart, then the connected store URL + /checkout/cart.
Payment assist
Each payment.failed is recorded in commerce_payment_failures: method code, total, currency, the error text with e-mail addresses and runs of six or more digits masked, the e-mail only as the keyed hash — kept 90 days. Then:
- When the failure can be tied to the shopper's chat — the event carried the chat visitor id, i.e. the shopper had written in the chat on this store, cookie consent allowed the
cvr_att_vidcookie and Revenue attribution is on — your team sees "A payment failed at checkout (method, amount)" on that conversation in the Conviro inbox (a staff-only row; the shopper never sees it), and - only while payment assist is switched on and confirmed, the chat widget offers the shopper help once, on their next page view: "It looks like your payment didn't go through. Can I help you complete your order?" — shown in the widget's language (every widget locale) as a message from the assistant in their conversation. It is not repeated for the same failure (several failures in a row share one offer), is not shown while a person from your team is handling the conversation, expires 24 hours after the failure, and is withdrawn if you switch payment assist off (or the customer is deleted) before it was shown. Nothing is sent by e-mail.
- Otherwise Conviro only records the failure.
Measured: the module side on the local stack (payment-assist.sh, 12 checks — what is queued when, with and without consent); the backend on Postgres (payment-assist.pg.spec.ts: one offer under five parallel page views, withdrawn, expired, deleted conversation) and the widget page-view path (widget-pageview.service.spec.ts). Not yet run against the deployed backend.
Upgrading from 1.3.x — the confirmation hold
In 1.3.x these switches were read at default scope only, and the payment hook was never called by Magento's default checkout, so a switch turned on in 1.3.x never sent anything. In 1.4.0 they work per website and the payment hook fires — so upgrading would start sending cart contents and shopper e-mails at once.
Instead, setup:upgrade runs the data patch HoldCartEventsUntilConfirmed once: for each switch that is on at any scope, it writes the matching confirmation as 0 (unless a confirmation value already exists) and records the time in sync/confirmation_required_since. Result:
- nothing is sent until you confirm — on the confirmation page the admin message links to (Conviro › Confirm cart and payment data sharing, 1.4.1), in wizard step 5, or on the configuration page;
- the Integration Health card shows "… is switched on but not confirmed, so no cart.updated / checkout.started event is sent to Conviro (held since the upgrade to 1.4, <date> UTC)";
- since 1.4.1 every admin page of a connected store also shows it as a system message (severity major), until you confirm or switch the feature off. Its link opens a page that lists what each held feature sends and confirms only the features you tick: it writes the confirmation and tells Conviro, and nothing else — unlike Save in wizard step 5, it starts no catalog, order or customer sync and changes no other choice. A feature that is switched off cannot be confirmed there.
Measured on the local stack: the patch held an enabled cart switch and no cart event was queued until it was confirmed in step 5 (setup-wizard.sh).