# Post-purchase best practices Source: https://docs.aftersell.com/aftersell/best_practices A complete strategy guide for building, optimizing, and scaling your post-purchase upsell funnels in Aftersell # Post-purchase best practices This guide covers everything you need to build a high-performing post-purchase upsell strategy in Aftersell - from funnel architecture and product selection to discount strategy, copy and design, industry-specific playbooks, and testing. Whether you are setting up your first funnel or optimizing an existing setup, these best practices are based on patterns from top-performing Aftersell merchants. Want real-world examples from top brands? [Download our Upsell Playbook](https://www.aftersell.com/upsell-playbook) for proven strategies and case studies you can apply to your store today. Looking for checkout widget best practices? See [Checkout Best Practices](/aftersell/checkout_best_practices). *** ## Funnel architecture Your funnel architecture determines which customers see which offers, and in what order. Getting this right is the single biggest lever for post-purchase revenue. ### How the post-purchase funnel flow works Before building funnels, make sure you understand how the offer flow works. For a full walkthrough, see [Post-purchase Overview](/aftersell/post_purchase_overview). In short: after checkout, Upsell #1 is shown. If the customer accepts, Upsell #2 is shown as a follow-up. If the customer declines, a Downsell is shown instead. After all offers are completed, the customer lands on the Thank You Page. Shopify limits customers to a maximum of 3 accepted post-purchase offers per order. Only one product can be selected per upsell step. Plan your funnel depth with these limits in mind. ### Start with your hero products Build dedicated funnels for your 3 to 6 highest-volume products first. These are the items that generate 60 to 80% of your store's revenue, and targeting them ensures your highest-traffic orders always see a relevant, optimized upsell. Traits of a hero product: * High sales volume and strong contribution to profitability * Market leadership in their category * Broad customer appeal and positive reviews * Receives dedicated marketing efforts and promotion ### Set up a catch-all funnel A catch-all funnel ensures that every order - even those that do not match your hero product funnels - still sees an upsell offer. This is one of the most commonly missed steps, and skipping it means leaving revenue on the table. How to set it up: 1. Set the trigger to "Show for All Customers" 2. Assign it the **lowest priority** so it only fires when no other funnel matches 3. Include Thank You Page upsells in this funnel for full post-purchase coverage You can adjust funnel priority by clicking the **Manage Priority** button at the top right of the funnel table. ### Use Smart Funnel as your first layer [Smart Funnel](/aftersell/smart_funnel) uses Rokt's AI and machine learning models to automatically select the most relevant upsell offer for each customer. It evaluates at Priority 0 (before all manual funnels), making it a powerful first layer in your strategy. We recommend enabling Smart Funnel alongside your manual funnels. It handles the dynamic targeting automatically while your manual funnels cover specific use cases, Thank You Page offers, and edge cases Smart Funnel does not reach. Smart Funnel currently only supports English. If your store serves customers in other languages, use manual funnels for those audiences until multilingual support is available. ### Add follow-up offers to your funnel Do not stop at the first offer. A well-structured funnel includes offers on both the accept and decline paths: * **Upsell #1** - Your primary offer (highest-margin or most complementary product) * **Upsell #2** (accept path) - Shown when Upsell #1 is accepted. Use this for an additional complementary product or a related add-on * **Downsell #1** (decline path) - Shown when Upsell #1 is declined. Use this for a lower-price alternative or a smaller version of the original offer * **Thank You Page offers** - Product recommendations and upsells on the order confirmation page, shown to every customer regardless of what happened on the post-purchase page This means every customer sees at least two offers (one on the accept or decline path, plus the Thank You Page), and customers who engage see even more. Use AI-powered product recommendation widgets on the Thank You Page to keep engagement high. These widgets automatically surface relevant products based on what the customer purchased, without any manual configuration required. ### Manage funnel priority intentionally When multiple funnels match the same order, Aftersell uses the priority order to determine which one fires. Review your priority list regularly: * Hero product funnels should have higher priority than your catch-all * Smart Funnel always evaluates at Priority 0 (highest) * Seasonal or promotional funnels should be temporarily elevated during campaigns *** ## Product selection Choosing the right products to upsell has a direct impact on conversion rate. The goal is relevance - customers are far more likely to accept an offer that feels like a natural extension of what they just bought. ### Complementary products outperform same-product offers Upselling a complementary product (for example, sandals with a dress, a phone case with a phone, a serum with a moisturizer) consistently outperforms offering the same product the customer just purchased. The exception is consumable or replenishable products where buying a second unit makes sense. ### Strategic product placement across the funnel Since the funnel flow is based on accept and decline actions, think strategically about what goes where: * **Upsell #1:** Your strongest, most complementary offer with the highest expected conversion rate * **Upsell #2 (accept path):** The customer just said yes - they are engaged. Show a second complementary item or a related add-on. This is a warm audience * **Downsell #1 (decline path):** The customer said no to the first offer. Show a lower-price alternative, a smaller size, or a different product category. Reduce the commitment level to recover the conversion ### AI recommendations vs. manual selection Aftersell supports both AI-powered and manually selected product offers: * **AI recommendations (automatic upsells)** use Shopify's Recommendation API to suggest complementary products based on the customer's order. The recommendations consider factors like purchase correlation, order frequency, and product affinity. For stores with very few orders or recently added products, Shopify may not have enough data to generate recommendations - in that case, you can manually add related products in the Shopify Search & Discovery app. You can exclude products from automatic upsells by selecting collections under **Settings > Automatic upsells > Excluded products** - products in the selected collections are not used. * **Manual selection** gives you full control over exactly which products appear. This is best for curated campaigns, seasonal promotions, or when you know your catalog deeply. When using automatic upsells (AI recommendations), you can enable a setting to skip the offer if the product already exists in the original order. In Smart Funnel, this is the "Skip Products in Original Order" toggle. In regular funnels, this is in the Product Details widget settings. We recommend keeping this enabled to avoid offering the customer a product they just purchased. This setting does not apply to the Most Expensive or Least Expensive in Cart product types, which are designed to re-offer items from the original order. We recommend A/B testing AI vs. manual to see which performs better for your store. Many merchants find that AI outperforms manual selection for high-traffic, diverse catalogs, while manual selection wins for stores with a smaller, curated product line. ### Quantity defaults For lower-cost or consumable products, test offering a default quantity of 2 instead of 1. If the x2 offer is accepted more often, it means increased revenue with no extra effort. This works especially well for supplements, food items, skincare, and other replenishable goods. *** ## Discount strategy Discounts are one of the strongest levers for post-purchase conversion, but the approach matters more than the amount. ### Always offer a discount on post-purchase upsells Post-purchase offers convert significantly better with a discount than without one. The customer has already committed to a purchase and is in a buying mindset - a discount at this moment feels like a reward, not a sales tactic. For best performance, set a non-zero Max Discount for Smart Funnel. Smart Funnel templates do not dynamically adjust based on the discount field value, so a non-zero Max Discount tends to convert best. ### Use compare-at pricing Enable compare-at pricing to visually emphasize the value of your upsell offer. Displaying a higher "compare at" price alongside a lower discounted price makes the deal feel more compelling, even with a smaller actual discount. Example: * Regular price: \$20 * Compare at price: \$25 * Customer sees: ~~\$25~~ \$20 The visible discount percentage may differ from what you set in upsell settings when "Use Compare at Price" is enabled, since the compare-at price can inflate the perceived discount. Always double-check how it renders on the page by placing a test order. ### Round your discount percentages Always round to the nearest 5th - for example, offer 25% or 30% instead of 27%. Round numbers look more intentional and can boost conversion rates. ### Finding the right discount level A/B test different discount levels to find the sweet spot for your store. The goal is to determine how low you can set the discount without hurting your conversion rate. Common starting points by category: * **Fashion and apparel:** 10-20% off * **Supplements and health:** 15-25% off * **Beauty and skincare:** 10-20% off * **Food and beverage:** 15-25% off * **Electronics and accessories:** 5-15% off * **Home goods:** 10-20% off These are starting ranges for testing - your optimal discount depends on your margins, product pricing, and customer behavior. ### Discount strategy across the funnel Consider varying your discount by funnel position: * **Upsell #1:** Your standard discount (for example, 15% off) * **Upsell #2 (accept path):** Can be the same or slightly lower - the customer is already engaged and buying * **Downsell #1 (decline path):** Consider a slightly higher discount to recover the customer who just said no. A bigger discount on a lower-price item can be very effective here ### When to use percentage vs. fixed dollar discounts * **Percentage discounts** work better for higher-priced items where the dollar savings feel significant (for example, "20% off" on a \$100 item = \$20 saved) * **Fixed dollar discounts** work better for lower-priced items where a percentage feels small (for example, "\$5 off" feels better than "10% off" on a \$50 item) A/B test both formats to see which resonates with your customers. *** ## Copy and design First impressions are crucial on post-purchase pages. Customers make snap judgments, so your value proposition needs to be impossible to miss. ### Emphasize key points with bold text and color Draw attention to the most persuasive elements of your upsell page. Phrases worth highlighting: * The discount percentage or dollar amount * "LIMITED TIME" or urgency language * Countdown timers * Free shipping mentions ### Write clear, benefit-focused headlines Your headline should tell the customer exactly what they are getting and why it matters. Lead with the benefit, not the product name. * Good: "Complete your look - 20% off matching accessories" * Avoid: "You might also like these products" ### Configure your accept and decline buttons intentionally The [Buttons widget](/aftersell/post_purchase_widgets) gives you control over how the accept and decline buttons behave and appear. However, Shopify requires that the accept and decline button text follows strict guidelines - the button wording cannot be customized, only translated into a selected language. What you can configure: * **Accept button text** - Choose between "Pay Now" (displays "Pay now - Product total price") or "Accept Offer" (displays "Accept offer - Product total price") * **Button language** - Select from all supported Shopify Checkout locales to automatically translate both accept and decline button text into the customer's language * **Button layout** - Choose accept above decline, decline above accept, or side by side * **Decline button style** - Secondary or link format * **Button alignment and width** - Adjust positioning to match your offer design * **Supporting text** - Add optional text above or below the buttons with styling controls and dynamic variable support The accept and decline button text cannot be freely written or customized beyond the two options listed above. This is a Shopify platform restriction, not an Aftersell limitation. The decline button text is automatically set and can only be translated, not edited. ### "Require Confirmation Click to Accept" "Require Confirmation Click to Accept" is available in the Buttons widget for individual offers. This setting adds a second confirmation step before an upsell is accepted. It is worth being aware of if you are using the Most Expensive or Least Expensive in Cart product types, which re-offer items from the customer's original order. If you find that customers are reaching out about unintended purchases on these offer types, this setting can help. It is not needed for all offers, as the additional step may reduce conversion rates. [Learn more →](/aftersell/post_purchase_widgets) ### Long-form vs. short-form offer pages * **Short-form pages** offer concise information, faster load times, and a streamlined experience. They work well for lower-priced, impulse-friendly products. * **Long-form pages** provide detailed product descriptions, features, benefits, and additional images. They work better for higher-ticket products where customers need more information before committing. We generally recommend starting with short-form and testing long-form for higher-ticket items. ### Multi-step offers within a single page If you want to show multiple products on a single upsell page (for example, three accessories on Upsell #1), you can use [multi-step offers](/aftersell/how_to_create_a_multi_step_post_purchase_upsell). Multi-step splits a single page into sequential steps where each step shows a different product. If the customer declines a step, they see the next step on the same page. If they accept, they move to the next page in the funnel (for example, from Upsell #1 to Upsell #2). Multi-step is only available for multi-product upsells and supports up to 12 products per page. We recommend keeping the number of steps minimal for a smooth customer experience. *** ## Thank You Page strategy Not every order qualifies for Post-purchase upsells due to [Shopify's post-purchase restrictions](/aftersell/why_isnt_my_1_click_offer_displaying). Thank You Page upsells act as a fallback, ensuring those customers still see an offer. Unlike Post-purchase offers, Thank You Page offers work with all payment methods. ### Include Thank You Page offers in every funnel Set up Thank You Page upsells in every funnel, including your catch-all. Each funnel's Thank You Page widgets must be configured individually - there is no way to standardize them across multiple funnels. This means if you have 5 funnels, you need to configure the TYP section in each one. Step by step: 1. Open your funnel in the Aftersell admin 2. Scroll to the **Thank You Page** section 3. Click **Add Widget** and select **Product Recommendation** 4. Choose your product selection method, configure your discount, and save 5. Repeat for each funnel, including your catch-all ### Choose the right product selection method Thank You Page product recommendation widgets support three selection methods. Choose the one that fits your store: * **Automatic Upsells** - Lets Aftersell recommend products based on the customer's cart contents. This is the easiest option and tends to convert well because the recommendations are personalized to what the customer just bought. Start here if you are unsure which products to show. * **Specific Products** - Manually select up to 10 products to display. Use this when you want full control, such as promoting a specific product, clearing overstock, or running a seasonal campaign. * **Collections** - Display products from a specific Shopify collection. Use this when you want variety within a curated set (for example, showing items from the same collection the customer purchased from). Enable **Hide product if purchased** to avoid showing items the customer already bought, and **Hide out-of-stock variants** to only display available products. Both settings are in the product recommendation widget configuration. ### Apply a discount to your TYP offers You can apply a percentage or fixed dollar discount directly within the TYP widget. We recommend always including a discount on Thank You Page upsells to give customers a reason to act. Use compare-at price display to visually show the savings. ### Set the right order handling method When a customer accepts a Thank You Page upsell, you choose how the order is processed: * **Modify original order** - Adds the upsell product to the existing order. Free shipping is automatically applied. Use this for a seamless experience where everything ships together. * **Create new draft order** - Creates a separate order for the upsell. Use this if your fulfillment workflow requires separate orders, if you want to offer free shipping only on the upsell, or if your upsells overlap with products in the original order. If your top-sellers are also your main upsell candidates, prefer **Create new draft order** - "Modify original order" silently hides upsells whose variant is already in the customer's order. Bundle products are also not supported with "Modify original order" - Shopify's order-edit API rejects them, so bundle upsells are either hidden or fulfilled as a separate draft order depending on your fallback behavior. See [Order Handling](/aftersell/thank_you_page_extensions_overview#order-handling) for the full trade-off breakdown. ### Use banner text to frame the offer Add a short banner headline above your product recommendations to give customers context. Framing like "Complete the look," "Pairs well with your order," or "Customers who bought this also loved" performs better than showing products with no context. ### Add the app block in Shopify After configuring your Thank You Page widgets in Aftersell, you must add the Aftersell TY widget app block to **both** the Thank You page **and** the Order Status page in your Shopify Editor, then enable it and save. Skipping this step will cause your Thank You Page widgets to not display for customers. This is one of the most common reasons Thank You Page widgets do not appear. If your TYP offers are not showing, check the Shopify Editor first before troubleshooting anything else. *** ## Upsell strategies by industry Different product categories have different upsell dynamics. For detailed playbooks tailored to your vertical - including recommended products, discount ranges, funnel triggers, and testing priorities for fashion, supplements, food and beverage, beauty, electronics, home goods, and automotive - see [Post-Purchase Strategies by Industry](/aftersell/post_purchase_strategies_by_industry). *** ## Testing A/B testing and multivariate testing are the most effective ways to improve funnel performance over time. See the full [Post-Purchase A/B Testing](/aftersell/post_purchase_a_b_testing) and [Post-Purchase Multivariate Testing](/aftersell/multivariate_testing) guides for detailed setup instructions. ### Key tests to prioritize These are the highest-impact tests based on patterns from top-performing merchants: 1. **AI (dynamic) vs. specific product (static) upsells** - Determines whether automated product matching outperforms your manual curation 2. **Default quantity 1 vs. 2** - Especially impactful for consumables and lower-cost products 3. **Long-form vs. short-form offer pages** - Tests whether customers need more information or prefer a streamlined experience 4. **Same product vs. complementary product** - Tests repurchase vs. cross-sell 5. **Single product vs. multi-product** - Tests simplicity vs. choice 6. **Varying discount percentages** - Finds the minimum discount needed to maintain conversion rate A/B testing for post-purchase uses Layout A through Layout E (up to 5 layouts). You cannot A/B test one funnel against another funnel - testing happens within a single funnel across layouts. A/B testing is only available for Post-purchase upsells and is not available for Thank You Page offers. For checkout widget testing, see [Checkout A/B Testing](/aftersell/checkout_a_b_testing). ### Data guidelines Before making changes to a funnel, ensure it has run for a minimum of 2 to 4 weeks or collected at least 100 to 200 impressions per layout. Changes made too early are based on insufficient data and can lead to misleading conclusions. Regularly analyze performance data to refine offers, placements, and product selections. An iterative approach helps identify high-conversion strategies while ensuring all changes are based on reliable data. Use the **Revenue per visit** metric as your primary performance indicator over time, as it accounts for unique visits rather than raw impressions. *** ## Common mistakes Avoid these pitfalls when setting up and optimizing your post-purchase funnels: ❌ **No catch-all funnel** - some orders will never see an upsell because they do not match any funnel triggers. Set up a catch-all funnel with the "Show for All Customers" trigger at the lowest priority so every order sees an offer. [Fix it →](/aftersell/quickstart_guide_to_aftersell) ❌ **No Thank You Page upsells** - orders that are ineligible for Post-purchase offers (due to Shopify payment method restrictions) go unconverted. Add Thank You Page upsells to every funnel, including your catch-all. Make sure to add the Aftersell TY widget app block to both the Thank You page and Order Status page in your Shopify Editor. [Fix it →](/aftersell/how_can_i_set_up_and_customize_thank_you_page_upsells_in_aftersell) ❌ **No downsell configured** - if a customer declines Upsell #1 and there is no downsell on the decline path, you have missed a second chance to convert. Always configure a downsell with a lower-price alternative for the decline path. You can add a downsell in the funnel editor when building your post-purchase funnel. [Fix it →](/aftersell/post_purchase_overview) ❌ **Irrelevant upsell offers** - generic offers that do not relate to what the customer bought reduce conversions and erode trust. Use collection-based triggers and complementary product selection to match offers to what the customer purchased. [Fix it →](/aftersell/how_to_configure_post_purchase_triggers) ❌ **Underutilizing AI tools** - missing out on dynamic personalization that often outperforms manual selection, especially for stores with large or diverse catalogs. Enable Smart Funnel and test AI recommendations in your manual funnels. [Fix it →](/aftersell/smart_funnel) ❌ **Making changes too early** - optimizing before collecting enough data leads to decisions based on noise rather than signal. Wait for at least 2 to 4 weeks or 100 to 200 impressions per layout before drawing conclusions. [Fix it →](/aftersell/analytics_in_aftersell) ❌ **Not testing** - running the same offer indefinitely without testing leaves performance gains on the table. Run at least one A/B test per quarter on your highest-traffic funnels. [Fix it →](/aftersell/post_purchase_a_b_testing) *** ## Need help? If you have questions about setting up or optimizing your post-purchase upsell strategy, chat with our support team using the live chat at the bottom right of the app. # Add-to-cart interception Source: https://docs.aftersell.com/aftersell/cart/add-to-cart-interception Why Aftersell takes over add-to-cart, how to tell whether a form is intercepted, and every way to opt a form out. When a shopper clicks **Add to cart**, Aftersell usually handles the add itself instead of letting the theme do it. This page explains why, what it means for scripts you've added, and how to turn it off for one form or for all of them. Most stores never need to change any of this. Read on if a script of yours stopped firing on add-to-cart, or if an add-to-cart button behaves oddly. ## What interception does Aftersell listens for the add-to-cart submit before the theme does. When it recognizes one, it: 1. Stops the event, so nothing else on the page handles that click. 2. Sends the add to Shopify itself. 3. Opens the Aftersell Cart drawer. Step 1 is the important one, and it's the reason this page exists. ## Why it exists Without it, both carts respond to the same click. The theme adds the item and opens its own drawer, Aftersell adds it and opens ours, and the shopper sees two carts, often with the item added twice. Stopping the event is the simplest way to guarantee one add and one cart. ## What it costs Stopping the event stops it for **everyone**, not just the theme. Any other code listening to that same add-to-cart stops running: your analytics, a tracking pixel, a subscription or bundle app, a script you added yourself. It fails quietly. Nothing appears in the browser console, and the add itself still works, so the usual symptom is a number that's wrong rather than something visibly broken: * `add_to_cart` events missing from GA4, Meta, or TikTok * A subscription or bundle app that works on the product page but not through the cart * Your own `addEventListener` on the form never firing If any of that sounds familiar, this page is the cause and the fix is below. ## When Aftersell doesn't intercept Interception isn't always on. Aftersell leaves add-to-cart alone when: * **It recognizes your theme's cart.** On themes Aftersell knows how to work with, it makes the theme's own cart inert instead of blocking the event, then lets the theme perform the add normally. Your scripts run as they always did. See [Which themes](#which-themes-aftersell-recognizes) below. * **The form doesn't add a line item.** A form with no variant `id` and no `items[]` is left alone. * **You've opted out** using one of the methods below. When Aftersell doesn't perform the add, it still watches for the cart request and opens the drawer when it sees one. See [Before you choose: what changes](#before-you-choose-what-changes). ## Which themes Aftersell recognizes | Theme | | | ---------------------------------------------- | ------------------------------------------------------------------------------------------- | | **Dawn** and the rest of Shopify's free family | Craft, Colorblock, Crave, Origin, Publisher, Refresh, Ride, Sense, Spotlight, Studio, Taste | | **Horizon** | Shopify's current default theme | | **Impulse** | | Aftersell matches on **how a theme is built**, not on its name, so a custom theme forked from any of these is normally recognized too, including private builds Aftersell has never seen. The reverse also happens: a heavily customized build can drift far enough from its parent that Aftersell no longer recognizes it, even though the theme is still called "Dawn". Being on this list makes recognition likely, not certain. ## Your options Choose the narrowest one that solves your problem. Each row gives up more than the one above it. | Option | Scope | Aftersell still opens the drawer | | -------------------------------------------------------------------- | ------------------------- | -------------------------------- | | [`registerSkipAddToCartRule`](#per-form-a-rule-in-code) | The forms your rule picks | Yes, from the cart request | | [`aftersell-cart-skip-atc`](#per-form-a-class-in-your-theme) | One form or button | Yes, from the cart request | | [`skip_add_to_cart_interceptor`](#whole-store-turn-interception-off) | Every form on the store | Yes, from the cart request | ### Before you choose: what changes Opting out hands the add back to your theme, which raises two questions worth answering before you pick a row: whether your cart still opens, and whether the theme's cart turns up next to it. #### Will your cart still open? Usually yes, with no work on your part. Whoever performs the add, Aftersell watches for the request going to Shopify and opens the drawer when it sees one, following your normal **Open cart when an item is added** setting. You don't have to call anything yourself. Three situations break that, and all three have a fix: **The add goes somewhere other than Shopify's cart endpoints.** Aftersell watches `/cart/add`, `/cart/change`, `/cart/update` and `/cart/clear` on your own domain. An app that adds through its own endpoint and syncs the cart afterwards isn't visible to this. Open the cart yourself once that app's add finishes: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} window.aftersell.cart.actions.refresh().then(() => { window.aftersell.cart.actions.open(); }); ``` **More than about three seconds pass between the click and the request.** Aftersell treats an add that closely follows a real click or keypress as shopper-driven. Beyond that window it's considered a background add, which doesn't open the drawer unless you opt in: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} window.aftersell.cart.configure({ open_on_background_add: true }); ``` **Your cart setting says not to.** If **Open cart when an item is added** is off, or you've set `open_on_add_to_cart: 'never'`, nothing opens the drawer. That's working as configured. #### Will the theme's cart open too? This is the risk the opt-outs carry, and the answer depends on your theme. Making the theme's cart inert is **separate from interception** and happens at page load either way, so none of the opt-outs here switch it back on. On a theme from the [recognized list](#which-themes-aftersell-recognizes), the theme's own cart stays quiet and the shopper sees one cart, yours. On a theme Aftersell doesn't recognize, there's nothing holding the theme's cart back. Opting out means the theme handles the add exactly as it always did, including opening its own drawer or redirecting to `/cart`, while Aftersell opens its drawer from the request it saw. That's two carts, and it's the reason interception exists in the first place. If that happens, you have three choices: leave interception on for that form, use a narrower opt-out that doesn't cover the forms causing it, or stop the theme's own cart yourself in your theme code. Turn an opt-out on in a test or unpublished theme first. If the theme's own cart appears where it didn't before, your theme isn't one Aftersell recognizes, and you'll want to keep interception on for those forms. This applies to add-to-cart only. Making the **cart icon** bypass Aftersell with the `aftersell-cart-wont-open-cart` class is different: a cart-icon click sends no request, so there's nothing for Aftersell to watch, and the drawer will not open. See below. ### Per form: a rule in code The preferred option. Register a rule that returns `true` for the forms you want left alone: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} window.aftersell.cart.hooks.registerSkipAddToCartRule((form) => form.hasAttribute('data-skip-aftersell') ); ``` Put it in **Cart settings → Custom script → Initialization**. Rules are additive: yours runs alongside any others, and any rule returning `true` skips that form. Full details in [Hooks](/aftersell/cart/sdk-hooks#registerskipaddtocartrule). ### Per form: a class in your theme If you'd rather not write a rule, add the `aftersell-cart-skip-atc` class in your theme: ```html theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
``` For a form submit, the class must be on the **form element itself**. A parent `div` won't work. For a button that adds to the cart without a form submit, the class can be on the button or any element around it. ### Whole store: turn interception off The blunt option. Add-to-cart behaves exactly as your theme originally did, on every form: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} window.aftersell.cart.configure({ skip_add_to_cart_interceptor: true }); ``` This one is read **once, when the cart loads**. It only works from your cart's **Initialization** script. Setting it later, inside `ready()` or from an event handler, does nothing and fails silently. Reach for this only when the per-form options don't fit, for example when the forms you need to exempt are created by another app and you can't identify them reliably. ## The cart icon is separate The cart icon in your header is handled by its own interceptor, with its own opt-out. Turning off add-to-cart interception does not change what the cart icon does, and the reverse is also true. Clicking the cart icon opens the Aftersell drawer instead of going to `/cart`. To leave one icon or button alone, add the `aftersell-cart-wont-open-cart` class to it, or to any element around it: ```html theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} Cart ``` That control then does whatever your theme makes it do, usually going to the cart page. Aftersell is out of the picture entirely, so **the drawer will not open**. Unlike add-to-cart there's no request to watch for, so if you want your cart to open from that control you have to say so: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} document.querySelector('#my-cart-link').addEventListener('click', (event) => { event.preventDefault(); window.aftersell.cart.actions.open(); }); ``` The same silencing problem applies here: because Aftersell stops the click, your analytics and pixels don't see cart-icon clicks either. If that's all you need to fix, keep the drawer and stop the silencing: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} window.aftersell.cart.configure({ skip_open_cart_interceptor: true }); ``` Your listeners run, the drawer still opens, and the click still doesn't navigate to `/cart`. Full details in [Configure](/aftersell/cart/sdk-configure#skip_open_cart_interceptor). To change *which* elements open the cart rather than turning them off, use **Cart settings → Advanced → Cart icon selector** instead of editing your theme. ## Where to go next * **[Configure](/aftersell/cart/sdk-configure)**: every SDK option, including the ones referenced here. * **[Hooks](/aftersell/cart/sdk-hooks)**: per-form and per-line control. * **[Open the drawer from a page builder](/aftersell/cart/sdk-use-case-page-builder)**: for Replo, PageFly, GemPages, and custom buttons that add to the cart their own way. # Cart analytics Source: https://docs.aftersell.com/aftersell/cart/analytics Read per-cart performance for your Aftersell Cart — revenue, impressions, conversion, and top products. The **Analytics** page reports how your published carts are performing. This page covers the **cart** view — for per-variant test metrics, see [Test analytics](/aftersell/cart/test-analytics). ## Per-cart metrics Each cart's performance is shown over a date range you choose, with a change badge comparing it to the previous equal-length period: | Metric | What it means | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | **Revenue** | Revenue generated by the cart, shown as a stacked-area chart with a combined total. Add-ons and Upsells are displayed as separate stacked bands. | | **Cart impressions** | Unique times shoppers saw the cart. | | **Checkouts completed** | Orders completed from the cart. | | **Conversion rate** | Completed checkouts over impressions. | | **Subscription upgrades** | The **count** of subscription upgrades (not a revenue figure). | | **Top performing products** | The best-selling upsell and add-on products, with quantity and revenue. | An **overall** view also offers a **Compare** toggle to overlay the previous period. ## How the data is collected Analytics are built from your orders. When an order completes, Aftersell attributes it back to the cart and records impressions, conversions, and revenue, which roll up into the reports. Conversion rate is a straight per-day ratio: completed checkouts over cart impressions for each day in the range. ## Exporting The **Revenue**, **Conversion rate**, and **Subscription upgrades** charts each have an **Export to CSV** button that downloads the displayed series (including the comparison series if Compare is on). The KPI cards and Top products don't currently export. ## A note on revenue coverage The revenue figures count **upsell** and **add-on** revenue only — every revenue query on this page filters to those two categories. Subscription upgrades are reported separately, as a conversion count rather than a revenue figure, because the value recurs. This is a subset of everything your cart earns, not a full partition of it, so these figures won't reconcile against a store-wide revenue total. # Banner block Source: https://docs.aftersell.com/aftersell/cart/banner-block The Aftersell Cart Banner block: a message banner shown inside the drawer, with an optional countdown timer. > The **Banner** block is a message strip shown inside the cart, useful for promotions, shipping messages, or urgency prompts such as a free-shipping notice, a sale announcement, or a "cart reserved" prompt. It can include a live countdown timer. Banner block in the Aftersell cart drawer showing a reservation countdown message ## Behavior * **The countdown only runs when all three conditions are met:** the timer is enabled, the text contains the `{{timer}}` token, and the duration is greater than zero. Otherwise the banner shows as static text. * The timer counts down in `MM:SS` and is remembered for the shopper's tab (it survives navigation within your store during the session), so it doesn't restart on every page. * **When the timer reaches `00:00`, the entire banner disappears**, so shoppers never see a zeroed-out clock. * In the editor preview the timer loops and the banner never hides, so you can keep styling it. ## Settings | Setting | What it controls | Default | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | | **Text** | The rich-text message. Include the `{{timer}}` token to show a countdown. | `Your cart is reserved for {{timer}} minutes!` | | **Countdown timer** | Turns the countdown on or off. | On | | **Minutes** / **Seconds** | How long the countdown runs. Two number fields, shown once **Countdown timer** is on and displayed as `MM:SS` where `{{timer}}` appears. | 10 minutes | The text is translatable. ## Placement and limits * **Region:** any (top, body, or bottom). * **Maximum:** 3 per cart state — the filled cart and the empty cart each get their own allowance. * **State:** both filled and empty cart. * Added to new carts by default. Not locked, so you can remove or hide it. ## Custom template Supports a [custom template](/aftersell/cart/custom-templates) from its Code tab, which replaces this block's built-in markup with your JSX. These are the props it receives. | Prop | Type | What it's for | | ----------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- | | `text` | `string` | The banner message as sanitized HTML, with the `{{timer}}` token **already replaced** by the live countdown. | | `shouldUseTimer` | `boolean` | `true` when the countdown is running for this banner. | | `isTimerExpiredAndShouldHide` | `boolean` | `true` once the countdown has reached zero. | | `isLoading` | `boolean` | Always `false` here: the block renders its built-in skeleton during load and only calls your template once the cart is ready. | There's no separate `timer` prop. The countdown is interpolated into `text` for you, so rendering `text` is enough. ```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} function CustomTemplate(props) { // The built-in banner removes itself at 00:00; a custom template must do the same. if (props.shouldUseTimer && props.isTimerExpiredAndShouldHide) return null; return (
); } ``` That early return matters. Without it your banner keeps rendering after the timer expires, and because the token is already substituted, shoppers see a frozen `00:00`. ## Design Style this block with its **Design** section in the settings panel. These are per-block overrides that layer on top of your global design and fall back to it when blank. ### Text The **Text** section in Design lets you control the typography of the banner message. Bold and text color are set in the Rich Text Editor above (in the Settings tab), not here. | Setting | What it controls | Default | | ------------------ | -------------------------------- | ------------------- | | **Font** | Font family for the banner text. | Inherits from theme | | **Size** | Font size. | `14px` | | **Line height** | Line height multiplier. | `1.4` | | **Letter spacing** | Tracking between characters. | Normal | ### Style | Setting | What it controls | Default | | -------------------- | ------------------------------------------------------------------- | ----------- | | **Background color** | The banner's background fill. | `#000000` | | **Text color** | Fallback text color (overridden by the Rich Text Editor). | `#ffffff` | | **Border** | Whether the banner has a border — **None** (0px) or **Show** (1px). | None | | **Border color** | Color of the border when **Show** is selected. | Transparent | What are design settings? Learn more here: [Design settings](/aftersell/cart/design-settings). # How do blocks work? Source: https://docs.aftersell.com/aftersell/cart/blocks-overview Understand Aftersell Cart blocks: sections and sub-blocks, filled vs empty, limits, locked blocks, conditions, and per-block settings. Your cart's layout is a stack of **blocks**: configurable pieces you add, reorder, style, and customize in the cart editor. Which blocks you include, and in what order, is the cart shoppers see. For how blocks sit inside **states** and **sections**, see [How do carts work?](/aftersell/cart/how-carts-work). ## Blocks and sub-blocks There are two kinds of block: * **Blocks** sit directly in the cart, in one of three sections: **Header**, **Body**, or **Footer**. Each section offers a different set of blocks. * **Sub-blocks** nest inside another block. Today only [**Cart items**](/aftersell/cart/cart-items-block) hosts sub-blocks: the **Product** row (the line-item row itself), [**Subscription upgrade**](/aftersell/cart/subscription-upgrade-block), and [**Custom code**](/aftersell/cart/custom-code-blocks). ## Adding, reordering, and removing blocks * **Add** a block with the **Add block** picker. A block is greyed out if it can't go where you're adding it, or if you've reached its limit (the picker shows a `count/max` badge). * **Reorder** by dragging a block within its section. * **Remove** with the trash icon, except locked blocks (below). * **Show/hide** most blocks with the eye toggle, which hides a block from shoppers without deleting it. A few structural blocks can't be hidden: **Cart items**, **Checkout button**, and the **Product** row. ## Locked blocks Some blocks can be reordered but not deleted, so core cart behavior (for example, checking out) can't be removed by accident: * **Cart items** * **Checkout button** ## Default blocks New carts start with a working default layout: * **Filled cart:** Header, Banner, Cart items, Summary, Checkout button * **Empty cart:** Header, Empty cart block The **empty cart state** is the whole empty layout. The **Empty cart block** is one block inside it. See [How do carts work?](/aftersell/cart/how-carts-work) for the difference. ## How many of each block you can add Limits are counted **per cart state**, not per cart. The filled cart and the empty cart each get their own allowance, so a cart can hold three Banners in its filled layout and three more in its empty layout. Most blocks are limited to one per state. The exceptions: | Block | Maximum per cart state | | -------------- | ---------------------- | | Banner | 3 | | Image | 3 | | Product add-on | 3 | | Summary | 2 | | Custom code | Unlimited | ## Content, Design, and Code Each block is configured through up to three surfaces in the editor: * **Content**: the block's settings (text, product choices, thresholds, and so on). The **Custom code** block is the one exception: it has no Content panel because the block *is* the code. * **Design**: per-block styling that layers on top of your global [**Design settings**](/aftersell/cart/design-settings). Every block has one except **Custom code**, which has no settings panel at all. * **Code**: override the block's built-in rendering with a [**custom template**](/aftersell/cart/custom-templates). Most blocks support this; a couple don't. ## Show or hide by market, country, or currency Some blocks can show different settings, or hide entirely, based on who the buyer is. That is separate from the sidebar **eye toggle**, which turns a block on or off for everyone. | | **Eye toggle** | **Conditions** | | ---------------- | --------------------------------------------- | ------------------------------------------------------- | | **What it does** | Hide or show the whole block for all shoppers | Pick which settings variant a shopper sees (or nothing) | | **Based on** | Your choice in the editor | Shopify market, customer country, or customer currency | | **Where** | Sidebar eye icon on most blocks | Settings panel for blocks that support conditions | **Supported condition types today:** Shopify market, customer country, and customer currency (each with **In** or **Not in**). Cart total and cart contents are **not** condition types. Use [Rewards](/aftersell/cart/rewards-block) tier thresholds for spend/quantity progress, or the [Cart SDK](/aftersell/cart/sdk-overview) when you need a rule the editor can't express. Conditions are an ordered list: the **first matching** condition wins. Put specific rules above an **All buyers** catch-all. If nothing matches, the block renders nothing for that shopper. **In the editor today**, the full Conditions UI ships on the [**Rewards**](/aftersell/cart/rewards-block#per-market-rewards) block: different tier sets per market, country, or currency. Other blocks either use a single “all buyers” configuration or don't participate in this system yet. Editor preview does **not** evaluate the live buyer. Select a condition in the panel to preview that variant. ## All blocks **Structure** * [Header](/aftersell/cart/header-block): title, item count, logo, and close control, pinned to the top. * [Cart items](/aftersell/cart/cart-items-block): the items customers add to cart; repeats per line. * [Subscription upgrade](/aftersell/cart/subscription-upgrade-block): sub-block that offers to convert a line to a subscription. * [Summary](/aftersell/cart/summary-block): totals, savings, and applied discounts. * [Checkout button](/aftersell/cart/checkout-button-block): the primary call-to-action to checkout. * [Empty cart](/aftersell/cart/empty-cart-block): the content shown when the cart is empty. * [Express payments](/aftersell/cart/express-payments-block): accelerated checkout buttons (Shop Pay, PayPal, and so on) inside the cart. **Merchandising** * [Upsells](/aftersell/cart/upsells-block): strategy-picked product recommendations. * [Product add-on](/aftersell/cart/product-add-on-block): a single specific product offered as an add-on. * [Rewards](/aftersell/cart/rewards-block): tiered rewards such as free shipping or gifts. * [Shipping protection](/aftersell/cart/shipping-protection-block): an opt-in shipping-protection add-on. **Shopper input** * [Discount code](/aftersell/cart/discount-code-block): a field to apply a discount code. * [Notes](/aftersell/cart/notes-block): an order-notes field. **Content** * [Banner](/aftersell/cart/banner-block): a message banner, with an optional countdown timer. * [Image](/aftersell/cart/image-block): a single image or a hosted preset such as payment icons. * [Custom code](/aftersell/cart/custom-code-blocks): custom HTML or React anywhere in the cart. **Extending** * [Custom templates](/aftersell/cart/custom-templates): override how any block renders from its Code tab. ## Blocks available in each section Each section has a different set of blocks available. That keeps the layout focused and reduces clutter. | Section | Blocks available | | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | **Header** | Header, Banner, Rewards, Image, Custom code | | **Body** | Banner, Notes, Discount code, Cart items, Empty cart, Custom code, Rewards, Product add-on, Shipping protection, Image, Upsells | | **Footer** | Banner, Notes, Discount code, Custom code, Rewards, Product add-on, Shipping protection, Express payments, Image, Upsells, Summary, Checkout button | Some of those blocks are state-specific (for example Empty cart only in the empty state). See [How do carts work?](/aftersell/cart/how-carts-work). ## Block validation errors If a block's settings contain an invalid value, a small red dot appears next to that block's name in the sidebar. The dot stays until you fix the problem. It isn't a dismissible notification. While any block has an error, **saving is blocked**. The **Save** button stays clickable, but selecting it shows an error toast (*"Fix the errors in your cart blocks before saving"*) and jumps to the first block with a problem, opening its settings so you can correct the highlighted field. **Publish** additionally requires no unsaved changes, so it stays unavailable until a clean save succeeds. Once the invalid field is corrected the dot disappears on its own, and saving proceeds normally. Hidden blocks are still validated. A block you've hidden can hold an invalid setting, show an error dot, and block saving exactly like a visible one, so if saving is blocked and every visible block looks fine, check your hidden blocks. # Cart items block Source: https://docs.aftersell.com/aftersell/cart/cart-items-block The Cart items block: the line-item list, the Product row, and the host for nested sub-blocks. > The **Cart items** block is the list of line items in the cart, rendering each product the shopper has added with its image, title, variant, price, quantity stepper, and remove control. It's a required block, and it's the container that hosts the cart's sub-blocks (the **Product** row, [**Subscription upgrade**](/aftersell/cart/subscription-upgrade-block), and [**Custom code**](/aftersell/cart/custom-code-blocks)), providing the structure that per-line sub-blocks attach to. Cart items block showing line items with product image, title, variant, price, quantity stepper, and remove control ## The Product row Inside Cart items sits the **Product** sub-block: the actual line-item row. It's locked and added automatically, so every Cart items block always has exactly one Product row that you can't remove; you reposition other sub-blocks around it. Its settings control how each line's pricing is displayed: | Setting | What it controls | Default | | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | | **Strike-through price** | Which price is shown struck through: **Compare-at or pre-discount, whichever is higher**, **Compare-at price**, **Pre-discount price**, or **No strike-through**. | Compare-at or pre-discount, whichever is higher | | **Strike-through price for subscriptions** | The same choice for subscription lines, with two differences: an extra **Subscription compare-at price** option, and **Compare-at price** renamed **Product compare-at, then subscription compare-at**. | Compare-at or pre-discount, whichever is higher | | **Savings label** | Whether savings show as an **Amount**, a **Percentage**, or are **Hidden**. | Amount | | **Bundle price** | How the displayed price is calculated for bundle lines. **Automatic** shows the total of all items in the bundle (or the main item's price when the other items are free). **Main item price only** shows only the main (anchor) item's price. This is a display label only — Shopify's cart total is always authoritative. | Automatic | | **Savings text** | The savings label. Supports the `{{value}}` token. | `Save {{value}}` | The row itself renders the product image (linking to the product page when available), title, variant, price and any struck compare-at price, a quantity stepper, and a remove button. Bundle lines show a disclosure list of their components. ### Text styling The Product row includes a **Text** section in its Design settings. Use it to control the typography of individual text elements in each line item. Select a text element from the picker to adjust its settings: | Setting | What it controls | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Text color** | Color of the selected text element. | | **Font** | **Theme font** (inherits your theme's font) or **Custom font** (enter the name of a font your theme already loads). Available for **Product title** only. | | **Size** | Font size in pixels. | | **Weight** | Font weight: Light, Regular, Medium, Semibold, or Bold. | | **Line height** | Line height as a multiplier of the font size (for example, `1.4`). | | **Letter spacing** | Letter spacing in pixels. Negative values tighten the text. | The text elements you can style are grouped by category: **Product** * **Product title** — the product name on each line. Also supports a custom font family. * **Variant** — the variant label (for example, *Size: Medium*). * **Subscription plan** — the read-only plan label shown on subscription lines. **Pricing** * **Price** — the line's current price. * **Compare-at price** — the struck-through original price. * **Savings** — the savings label (for example, *Save \$5.00*). Size and line height only — bold and color are set in the Rich Text Editor above. **Bundle** * **Bundle toggle** — the disclosure header that expands a bundle's component list. * **Bundle item title** — the title of each component inside a bundle. * **Bundle item variant** — the variant label for each bundle component. Leaving any field blank keeps the element's default value. Clicking a text element directly in the cart preview highlights it and opens its controls in the panel automatically. ### Discount tags design The Product row includes a **Discount tags** section in its Design settings. Use it to style the discount tag pills that appear on each line item: | Setting | What it controls | Default | | -------------------- | ----------------------------------------- | --------- | | **Background color** | Fill color of the discount tag pill. | `#F1F1F1` | | **Text color** | Text color inside the discount tag pill. | `#585858` | | **Border radius** | Corner rounding of the discount tag pill. | `6px` | These settings apply only to line-item discount tags in the Cart items block. Discount code tags in the [Summary block](/aftersell/cart/summary-block) are styled separately. ## Sub-blocks and how they position Cart items is the only block that hosts sub-blocks. **Sub-blocks render once per line, inside every product row**, positioned relative to the pinned Product row: * Sub-blocks ordered **before** the Product row appear **above** the product content in each line. * Sub-blocks ordered **after** the Product row appear **below** the product content in each line. So a [Subscription upgrade](/aftersell/cart/subscription-upgrade-block) placed after the Product row shows beneath each eligible line, not once at the bottom of the whole list. ## Behavior * When the cart has no items, the drawer switches to the empty state and this block isn't shown. * **One cart change runs at a time.** While a quantity update or removal is in flight, the row's controls are disabled to keep the cart consistent, then re-enabled once the change settles. * Lowering a line's quantity below 1 removes it. A quantity the store rejects (for example, beyond available stock) re-syncs to the last valid value. * **Bundles change as a unit.** Adjusting the quantity on a bundle's anchor line scales the whole bundle in one operation — if a child is included at 3 per anchor, taking the anchor from 1 to 2 takes that child to 6. Removing the anchor removes every member of the bundle at once. * **Some bundles can't be re-quantified.** If any of a bundle's children is included at a fractional rate (1.5 per anchor, say), the quantity stepper on that bundle is locked: the +/− buttons and the quantity field are both disabled, and typed quantities aren't accepted. The bundle can still be removed. * **Subscription lines show their plan.** When a line has a selling plan and the [Subscription upgrade](/aftersell/cart/subscription-upgrade-block) sub-block is turned off or not added, the Product row shows a read-only plan label beneath the variant — for example, *Delivers every month (save 30%)*. When that sub-block is enabled it presents the plan in its own picker, so the read-only label is suppressed rather than duplicated. ## Placement and limits * **Region:** body. * **Maximum:** 1 per cart state. * **State:** filled cart only. * **Locked and added by default.** Cart items can't be removed or hidden, only repositioned. ## Custom template Supports a [custom template](/aftersell/cart/custom-templates) from its Code tab, which replaces this block's built-in markup with your JSX. These are the props it receives. The **Cart items** container has no custom template. The **Product** row inside it does, and it's the richest surface in the cart: your template renders once per line. ### Line content | Prop | Type | What it's for | | ------------------ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `title` | `string` | Product title, as plain text. | | `variantTitle` | `string \| null` | Variant label. `null` for single-variant products and native bundles. | | `url` | `string \| null` | Product page URL. `null` when the line shouldn't link out. | | `imageUrl` | `string \| null` | Line image. `null` when the product has none. | | `quantity` | `number` | Current quantity on the line. | | `price` | `string` | Line price, **already formatted**. | | `compareAtPrice` | `string \| null` | The struck-through "was" price, already formatted. `null` when there's nothing to strike. | | `savingsHtml` | `string \| null` | Savings label as sanitized HTML. `null` when hidden or there's no saving. | | `discountTags` | `string[]` | Titles of discounts on this line, e.g. `['Spring Sale']`. `[]` when none. | | `sellingPlanLabel` | `string \| null` | Read-only subscription plan name. `null` when it's a one-time line, or when the [Subscription upgrade](/aftersell/cart/subscription-upgrade-block#custom-template) sub-block is rendering the plan UI instead. | | `bundle` | `object \| null` | [Bundle](/aftersell/cart/sdk-cart-object#bundles) view model on an anchor line. `null` otherwise. | | `productId` | `number` | Shopify product ID. | | `variantId` | `number` | Shopify variant ID. | | `line` | `AftersellCartLine` | The full [cart line](/aftersell/cart/sdk-cart-object#cart-lines), for anything the props above don't cover. | | `formatMoney` | `(cents: number) => string` | Formats a minor-unit amount. Use it for prices you read off `line`. | **`price` and `compareAtPrice` are formatted strings; everything on `line` is in cents.** Don't do arithmetic on `price`. Compute from `line.finalLinePrice` and friends, then run the result through `formatMoney`. ### Quantity and removal | Prop | Type | What it's for | | ------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `increment` | `() => void` | Adds one to the line. | | `decrement` | `() => void` | Removes one from the line. | | `remove` | `() => void` | Removes the line entirely. | | `quantityInput` | `string` | Current value for a controlled quantity ``. A string, so mid-typing states survive. | | `onQuantityInput` | `(event: Event) => void` | `onInput` handler for that field. | | `commitQuantity` | `() => void` | Applies the typed quantity. Wire to `onBlur`. | | `onQuantityKeyDown` | `(event: KeyboardEvent) => void` | `onKeyDown` handler, so Enter commits. | | `busy` | `boolean` | `true` while any cart mutation is in flight. Disable your controls on this. | | `pending` | `'increment' \| 'decrement' \| 'remove' \| null` | Which action is currently in flight, for a targeted spinner. | | `stepperLocked` | `boolean` | `true` when quantity can't be changed, because the line is a bundle anchor with a child included at a fractional per-anchor rate. Hide or disable the stepper — the built-in handlers already reject changes while it's set. | ```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} function CustomTemplate(props) { return (
{props.imageUrl && }
{props.url ? {props.title} : {props.title}} {props.variantTitle &&
{props.variantTitle}
} {props.sellingPlanLabel &&
{props.sellingPlanLabel}
} {props.discountTags.map((tag) => ( {tag} ))} {!props.stepperLocked && (
)}
{props.price}
{props.compareAtPrice && {props.compareAtPrice}} {props.savingsHtml &&
}
); } ``` ### Rendering a bundle On a bundle's anchor line, `bundle.children` holds its contents. Children never appear as their own rows, so if you don't render them the shopper won't see what's in the bundle: ```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} function CustomTemplate(props) { return (
{props.title} {props.price}
{props.bundle && (
    {props.bundle.children.map((child, i) => (
  • {child.quantity} × {child.title}
  • ))}
)}
); } ``` A child's `key` is `null` for a Shopify native bundle component, so fall back to the index as above. ## Design Style this block with its **Design** section in the settings panel. These are per-block overrides that layer on top of your global design and fall back to it when blank. What are design settings? Learn more here: [Design settings](/aftersell/cart/design-settings). # Cart settings Source: https://docs.aftersell.com/aftersell/cart/cart-settings Behavior settings for the Aftersell Cart — when the drawer opens and the theme selectors that keep your storefront in sync. Beyond [styling](/aftersell/cart/design-settings), the cart has a few **behavior** settings that control how it interacts with your storefront — when the drawer opens, and which theme elements Aftersell keeps in sync with the cart. ## Where to find these In the cart editor, open **Cart settings**. The options below are grouped under **Behavior** and **Custom selector**. ## Open the cart when an item is added **Open cart when an item is added** controls whether the drawer pops open automatically each time a shopper adds a product. It's on by default. Turn it off if you'd rather the cart stay closed until the shopper opens it themselves. ## Theme selectors Aftersell hooks into your storefront through CSS selectors — for example, to know which element opens the cart, or which cart-icon count to keep in sync. Built-in detection covers the most popular Shopify themes (Dawn, Sense, Crave, Debut, Impulse, Horizon, and many others), so **most stores never need to touch these**. Adjust a selector only if something isn't wiring up correctly on your theme. ### Selector modes Each selector offers the same three modes: | Mode | What it does | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Default** | Uses Aftersell's built-in detection for supported themes. | | **Default + custom** | Keeps the built-in detection and adds your own selector on top — use this when the default mostly works but misses an element (for example, a separate mobile icon). | | **Custom only** | Ignores the built-in detection and uses only your selector — use this when the default targets the wrong element or conflicts with your theme. | The selector input is enabled only for the **Default + custom** and **Custom only** modes. ### The three selectors | Selector | What it targets | Example | | ------------------------ | -------------------------------------------------------------------------------------------------------- | --------------------------- | | **Open cart selector** | The element(s) that should open the cart drawer. | `.header__cart-toggle` | | **Add to cart selector** | The add-to-cart button(s) Aftersell should hook into. | `.product-form__add-button` | | **Cart count selector** | The element on your theme's cart icon that displays the item count, so it stays in sync with the drawer. | `.header__cart-count span` | ### How to find a selector 1. Open your storefront in a browser (Chrome recommended). 2. Right-click the element you want to target — your cart icon, the count number, or the add-to-cart button — and choose **Inspect**. 3. In the panel that opens, find the element that represents it (the count is often a `span` inside the cart icon). 4. Note its class (starts with `.`) or ID (starts with `#`) — for example `.header__cart-count span` or `#CartCount`. 5. Back in **Cart settings**, set the selector to **Default + custom** or **Custom only** and paste it in. 6. Save, then test on both desktop and mobile. Start with **Default** — it works for most themes with no setup. Reach for **Default + custom** when only one of several icons updates (say, desktop works but mobile doesn't), and **Custom only** when the default is targeting the wrong element. If you're unsure which selector to use, your theme developer can point it out — you don't need to write any code, just copy and paste. # Checkout button block Source: https://docs.aftersell.com/aftersell/cart/checkout-button-block The Aftersell Cart Checkout button block: the required footer CTA that sends shoppers to checkout. > The **Checkout button** block is the primary call-to-action in the cart footer that takes shoppers to checkout, giving them a clear, prominent path from the cart to checkout. It's a required block. ## Behavior * The button resolves a **localized, market-correct checkout URL**, so shoppers land in the right market's checkout. If that can't be resolved, it falls back to the standard `/checkout` link. * With **Go to cart page instead of checkout** enabled, the button links to `/cart` instead. * Clicking navigates via JavaScript so a theme's own cart handling can't intercept it, while still respecting new-tab intents (Cmd/Ctrl-click, middle-click). * The click emits the SDK [`checkout` event](/aftersell/cart/sdk-events), which you can subscribe to. ## Settings | Setting | What it controls | Default | | --------------------------------------- | -------------------------------------------------------------------- | ---------------------------- | | **Button label** | Plain-text label entered in a text area. Supports `{{total_price}}`. | `Checkout • {{total_price}}` | | **Go to cart page instead of checkout** | Sends shoppers to your `/cart` page instead of straight to checkout. | Off | ## Placement and limits * **Region:** bottom. * **Maximum:** 1 per cart state. * **State:** filled cart only. * **Locked and added by default.** The Checkout button can't be removed or hidden, only repositioned within the footer. ## Custom template Supports a [custom template](/aftersell/cart/custom-templates) from its Code tab, which replaces this block's built-in markup with your JSX. These are the props it receives. | Prop | Type | What it's for | | ----------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | `label` | `string` | The button label as sanitized HTML, with `{{total_price}}` resolved. | | `href` | `string \| undefined` | The checkout URL. `undefined` in the editor preview, where there's nothing to navigate to. | | `isLoading` | `boolean` | Always `false` here: the block renders its built-in skeleton during load and only calls your template once the cart is ready. | **A custom checkout button loses checkout tracking.** The built-in button attaches a click handler that emits the SDK [`checkout` event](/aftersell/cart/sdk-events#checkout) and records the conversion for [cart analytics](/aftersell/cart/analytics). That handler is not passed to custom templates, so navigating via `href` alone skips both. If you need the event, emit it yourself from an `onClick` before navigation. Attribution reporting still can't be recovered this way, so prefer restyling the built-in button with [design settings](/aftersell/cart/design-settings) or [custom CSS](/aftersell/cart/custom-css) unless you truly need different markup. Render `href` as-is rather than defaulting it. An `` with no `href` is inert, which is the correct behavior in the editor. ## Design Style this block with its **Design** section in the settings panel. These are per-block overrides that layer on top of your global design and fall back to it when blank. What are design settings? Learn more here: [Design settings](/aftersell/cart/design-settings). # Creating carts Source: https://docs.aftersell.com/aftersell/cart/creating-carts Create a new Aftersell Cart, name it, save it as a draft, and publish it to your storefront. A **cart** in Aftersell is a configurable cart-drawer experience made up of [blocks](/aftersell/cart/blocks-overview). This page walks through creating your first cart and getting it live. ## Create a cart From the **Carts** page, click **Create cart**. Aftersell creates a new cart — named *Untitled cart 1*, *Untitled cart 2*, and so on, so each new one gets a distinct name — pre-seeded with a working default layout, and opens it in the cart editor. The default cart contains **Header → Banner → Cart items → Summary → Checkout button** for the filled state, and **Header → Empty cart** for the empty state (the empty state's Header is titled *Cart*). From there you [add, remove, and reorder blocks](/aftersell/cart/blocks-overview) to build the cart you want. New carts always start from this blank default layout. To start from an existing cart instead, use the **Duplicate** action on a cart in the Carts list. ## Name the cart Rename the cart inline from the editor's left sidebar — click the name and type. The name **saves immediately** on its own (it doesn't wait for the Save button). Blank or whitespace-only names are rejected and revert to the previous name. ## Draft and publish * Every new cart is a **draft**. Drafts aren't shown to shoppers — you can build and preview them freely. Use **Save** in the editor to persist your edits. * **Publish** makes the cart live. Because only one cart can be live at a time, **publishing a cart moves your current live cart back to draft** (see [Having multiple carts](/aftersell/cart/having-multiple-carts)). * **Unpublish** sets a live cart back to draft. With no live cart, the Aftersell Cart is disabled for shoppers until you publish another. ## Grant required permissions Before you can publish or serve a cart, Aftersell Cart needs a set of additional permissions from your Shopify store. If these haven't been granted yet, a banner appears at the top of the **Carts** page: > **Finish enabling your cart** — AfterSell Cart needs a few additional permissions to publish and serve carts on your storefront. Enable them to get started. Click **Update App** in the banner to open the permissions dialog and approve the request. The banner disappears automatically once all permissions are granted. If you arrive at the Carts page through an onboarding link, the permissions dialog may open automatically so you can approve in one step. ## Turn on the app embed For a published cart to actually render on your storefront, the **Aftersell Cart app embed must be enabled** in your theme. If it's off, the cart won't show even when published, and the Carts page flags the cart with an "App embed off" badge. The in-app setup guide walks you through the three steps: enable the app embed, create a cart, and publish it. ## Next steps * [Preview your cart](/aftersell/cart/previewing-carts) before publishing. * [Customize the look](/aftersell/cart/design-settings) with design settings. * [Add blocks](/aftersell/cart/blocks-overview) for upsells, rewards, and more. # Custom code blocks Source: https://docs.aftersell.com/aftersell/cart/custom-code-blocks The Aftersell Cart Custom code block: add your own HTML or React anywhere in the drawer, including inside Cart items. > The **Custom code** block adds your own HTML or React to the cart. Put it in any section of the drawer, or nest it inside [**Cart items**](/aftersell/cart/cart-items-block) as a sub-block so it repeats for each line. Unlike other blocks, it has no Content settings and no Design section: the block *is* the code, so you work entirely in its **Code** tab. Animated preview of adding and turning on a Custom code block in the Aftersell Cart editor ## Add and turn on a Custom code block 1. Add a **Custom code** block to any section, or as a sub-block under **Cart items**. 2. Select it and open the **Code** tab. 3. Choose **HTML** or **React component**. New blocks default to HTML. 4. Write your code. 5. If you chose React, click Compile. 6. Turn on **"Use custom template"**. For this block, that switch means “show my custom code”, and it defaults off, so nothing renders until you enable it. 7. Keep the sidebar eye toggle on so the block stays visible to shoppers. Both the eye toggle and **"Use custom template"** must be on for the block to appear. ## Behavior * The block renders nothing until the cart has loaded. * It also renders nothing when the sidebar eye is off, **"Use custom template"** is off, the code is empty, or React fails to compile or render. Because a failure is silent, check your block in [preview](/aftersell/cart/previewing-carts) before publishing. ## HTML mode HTML mode substitutes a small set of tokens into your markup. It’s for static or token-driven content, not for running logic. * **Inline ` ``` *After removing HTML & reworking ` ``` # Data and privacy Source: https://docs.aftersell.com/aftersell/customer_data_and_privacy What customer data Aftersell handles, how data-deletion and privacy requests work, and where to find the official privacy policy. This page explains, at a merchant level, what customer data Aftersell handles and how privacy and data-deletion requests are processed. It is a practical summary, not a legal document. The authoritative legal terms are in the [Rokt Privacy Policy](https://www.rokt.com/policies/privacy-policy) and the [Aftersell (powered by Rokt) Services Agreement](https://www.rokt.com/policies/aftersell-powered-by-rokt-services-agreement). Where this page and those policies differ, the policies apply. *** ## What data Aftersell handles Aftersell operates as an app installed on your Shopify store. Your Shopify store remains the canonical record of your customers — Aftersell stores only the limited identifiers it needs to attribute upsell offers to orders, such as checkout tokens, Shopify customer IDs, and offer/funnel journey records. Each Shopify store is treated as an independent data controller. Data belonging to one store is never mixed with, or exposed to, another store. If your store also uses **Rokt Thanks**, Rokt may process additional data to serve and measure partner offers. This is covered by the same [Rokt Privacy Policy](https://www.rokt.com/policies/privacy-policy) linked above, and shoppers can manage their preferences through the controls Rokt presents at the point of the offer. *** ## Data-privacy requests Aftersell supports Shopify's mandatory data-privacy (GDPR/CCPA) webhooks. When Shopify sends one of these requests on behalf of a shopper or a store, Aftersell handles it automatically: | Shopify request | What Aftersell does | | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Customer data request** (`customers/data_request`) | The request is logged internally. Because your Shopify store holds the canonical customer record and Aftersell stores only limited identifiers, there is usually little additional data to return; anything that needs manual fulfillment is escalated to [privacy@rokt.com](mailto:privacy@rokt.com). | | **Customer redact** (`customers/redact`) | Deletes the data associated with that customer. If your store uses Rokt Thanks, the deletion is also propagated to Rokt for that customer (this is an asynchronous process that can take up to 30 days to fully complete). | | **Shop redact** (`shop/redact`) | Fired after you uninstall the app. Cleans up your store's integration records. | You do not need to configure anything for these to work — they are handled for every store. *** ## Submitting a request * **Shoppers** should contact the store they purchased from. The store (as the data controller) can initiate a data request or deletion through Shopify, which Aftersell then honors automatically. * **Merchants** who need to escalate a specific data request — for example, exporting data that Rokt may hold for a Rokt Thanks–integrated store — can email [privacy@rokt.com](mailto:privacy@rokt.com). *** ## Data retention after cancellation When you cancel Aftersell, your settings, funnels, widgets, and configurations are retained for up to one year. Uninstalling does not delete them, so if you reinstall within that year they are simply still there — there is no restore step to run. After one year, that data may be removed. See [How do I cancel my Aftersell subscription?](/aftersell/how_do_i_cancel_my_aftersell_subscription) for the full cancellation flow. Uninstalling the app also triggers Shopify's `shop/redact` request, which cleans up your integration records as described above. *** **Related** * [Rokt Privacy Policy](https://www.rokt.com/policies/privacy-policy) * [Aftersell (powered by Rokt) Services Agreement](https://www.rokt.com/policies/aftersell-powered-by-rokt-services-agreement) * [How do I cancel my Aftersell subscription?](/aftersell/how_do_i_cancel_my_aftersell_subscription) # Does Aftersell have a developer API? Source: https://docs.aftersell.com/aftersell/does_aftersell_have_a_developer_api Aftersell does not provide a developer API. Shopify's Post Purchase API and Checkout Extensibility limit changes to those available in the app. Aftersell does not offer a general-purpose developer API for configuring the app. Due to the nature of working with Shopify's Post Purchase API and Checkout Extensibility environments we're limited in what we can edit, and all of the changes available to us are made in the app itself. There is one public API: the [Aftersell Strategies API](/aftersell/strategies_api_reference_evaluate_strategy). It evaluates a strategy against the context you send and returns the products to show. It is available on stores that have Aftersell Strategies enabled, and requests are authenticated with a store-specific API key you generate in the Aftersell admin and send in the `X-Strategy-Api-Key` header. # Does multi-currency checkout impact Aftersell? Source: https://docs.aftersell.com/aftersell/does_multi_currency_checkout_impact_aftersell This article explores how multi-currency checkout affects the functionality of Aftersell. If your store has multi-currency enabled, 1-click upsell offers will only appear for orders made in your **store's default currency.** For instance, if your store's default currency is GBP and the order was placed in USD, the offer will **not** display. This limitation is a result of Shopify's multi-currency infrastructure. \ To address this, consider aligning your store's default currency with the currency most commonly used by your customers. This can improve the visibility and performance of post-purchase upsells by providing a localized shopping experience. ### Steps for Changing Store Currency 1. Evaluate your customer base to determine the predominant purchasing currency. 2. Update your store's default currency in Shopify to match the target market's currency. 3. Wait for up to 24 hours for Shopify to fully convert your store to the new currency. 4. Verify that post-purchase upsells are visible to customers in the target market. No additional steps are required after the currency change for upsells to appear. This restriction is due to Shopify’s post-purchase limitations, which are explained further [here](/aftersell/why_isnt_my_1_click_offer_displaying). You can also review [Shopify's documentation](https://shopify.dev/docs/apps/checkout/product-offers/post-purchase#limitations-and-considerations) for additional details. Shopify's infrastructure imposes unique constraints on multi-currency capabilities, emphasizing the need for merchants to carefully plan their store's currency settings to optimize post-purchase app functionalities. *** [Thank you page](/aftersell/thank_you_page_scripts_overview) offers are not subject to the same limitations as 1-click offers, making them an excellent alternative in this scenario. We recommend setting up upsells to capture orders that may not see 1-click offers due to these restrictions. Moreover, setting up dedicated upsell offers tailored to key customer segments can further ensure these offers align with multi-currency functionalities. Consider leveraging Shopify Markets for enhanced configuration. # DTC ads onboarding guide | web pixel activation Source: https://docs.aftersell.com/aftersell/dtc_ads_onboarding_guide_web_pixel_activation This article outlines how to integrate the Rokt Conversions Web Pixel # **Overview** The Rokt Conversions Web Pixel enables accurate attribution of conversions from your Shopify store to Rokt campaigns. This helps optimize your marketing performance by tracking user activity through Shopify’s Web Pixels API. *** ## **Step 1: Install the Aftersell App** You will be provided with a special installation link by your account manager. * Click the link to be redirected to the Shopify App Store. * You will be prompted to install the Aftersell app. AfterSell by Rokt permission request listing customer data and pixel access scopes * Click **Install** to continue. After installation, Aftersell may display a permission request within the app for scopes related to pixel tracking — specifically `read_customer_events` and `write_pixels`. Click **Approve** to grant these permissions. Accepting these scopes allows Aftersell to inject and activate the Rokt Web Pixel automatically. *** ## **Step 2: Accept Terms and Conditions** After granting the required permissions: * You will be prompted to review and accept our Terms and Conditions. Rokt Thanks onboarding form with a Terms and Conditions checkbox and Enable now button * Press **Enable now** to proceed. *** ## **Step 3: Activate Free Plan** Following the Terms and Conditions: * You will be prompted to accept the **Aftersell Free Plan (Rokt Ads)**. * Click **Approve** to complete the activation. Shopify approval screen for the AfterSell Free Plan Rokt Ads charge with Approve button * Once approved, your onboarding is complete, and you will be redirected to the Rokt Ads dashboard, where you will see your newly created **One Platform Account ID**. (While it is being created the card reads *Generating One Platform Account ID*.) Welcome to Rokt Ads page showing the pixel activation notice and the account ID *** ## **Step 4: Web Pixel Activation** After completing onboarding, the Web Pixel installation will be triggered automatically. Please allow up to **5 minutes** for the activation to complete. *** ## **To Verify Pixel Activation:** 1. On the Rokt Ads page (inside Aftersell), click the link labeled **Customer Events Page**. This will take you directly to the right page in your Shopify Admin. 2. Alternatively:\ Navigate manually to Shopify Admin → Settings → Customer Events. 3. Once there:\ Under App Pixels, look for "Aftersell".\ Ensure the status is listed as Connected. Shopify Customer events settings showing the AfterSell by Rokt pixel marked Connected If the pixel does not appear immediately or shows "Disconnected," it may still be processing. Please wait a few minutes and refresh the page. *** ## **Additional Notes:** This activated web pixel does three things: 1. Adds a cookie when a customer lands on your site from one of your Rokt campaigns. Rokt will automatically add the “rtid” query parameter to the URL of the landing page. 2. Records conversions. If the customer has a cookie from step i) then the conversion will be attributed to your Rokt campaign. 3. Forwards Shopify's standard storefront events to Aftersell — page, product and collection views, searches, cart adds and removes, checkout steps, and checkout completion. This is the part that runs on analytics consent alone. The following settings will be applied automatically by the web pixel app. 1. *Permission: Analytics.* The pixel extension declares analytics consent only — marketing and preferences are both off. This is most relevant for customers in the EU and UK. Conversion sending is checked separately at runtime: if the shopper has not granted marketing consent, the Rokt conversion is skipped while the standard storefront events still flow. To learn more, see [Shopify’s documentation here](https://help.shopify.com/en/manual/promoting-marketing/pixels/custom-pixels/manage#customer-privacy). 2. *Data sale: Data collected does not qualify as data sale.* Conversion data is collected to optimize and monitor advertising campaigns and is not sold by Rokt. 3. For details on the Web Pixels API, see [Shopify’s developer documentation here](https://shopify.dev/docs/api/web-pixels-api). # Earn & Save program Source: https://docs.aftersell.com/aftersell/earn-save Earn & Save is an opt-in program for Aftersell merchants. When you enroll, two things happen each cycle: * Your Rokt Thanks earnings pay out to you in full. * Aftersell adds a matching discount on top of your Aftersell bill, sized to match your earnings from the last 30 days, up to your bill amount. If your earnings are less than your bill, the matching discount only covers part of the bill, and you still owe the remainder. Your Rokt Thanks earnings always pay out to you in full, regardless of whether the discount fully covers your bill. Earn & Save is not a trial, and it does not change your existing Aftersell plan. As long as Rokt Thanks stays active on your store and you remain enrolled, the matching discount keeps applying each cycle. Your features, your base plan price, and your maximum monthly charge all stay the same. ## How Earn & Save works Earn & Save has two sides: the earnings you generate through Rokt Thanks, and the matching discount Aftersell adds to your monthly bill. **Earn.** When you enable Rokt Thanks, vetted brands like Disney+, HelloFresh, and Venmo show their offers on your post-purchase confirmation page. Every time a customer clicks "Yes, please!" on one of those offers, you earn revenue. On average, merchants earn around \$0.30 to \$0.50 USD per transaction. Rokt pays these earnings out to you in full via PayPal (or wire/ACH if you have that set up). **Save.** Each billing cycle, Aftersell adds a matching discount on top of your Aftersell bill, sized to match your Rokt Thanks earnings from the last 30 days, up to your bill amount. The discount is added by Aftersell, not deducted from your earnings. If your earnings fully cover your bill, your Aftersell charge for that cycle can be as low as \$0. If your earnings are smaller than your bill, the discount only covers part of the bill and you pay the remainder. Either way, your Rokt Thanks earnings pay out to you in full. ## At a glance | | | | :-------------------------------- | :------------------------------------------------------------------------------------------------------------ | | **Who is it for?** | Any Aftersell store with 1,000 or more monthly orders. | | **What is it?** | An opt-in program layered on top of your existing pricing plan. | | **What does it cost?** | Nothing. There is no separate fee. | | **What changes about my plan?** | Nothing. Your features, base plan price, and maximum monthly charge stay the same. | | **When does the discount start?** | On your upcoming Aftersell bill, irrespective of how long you have been enrolled. | | **Where do my earnings go?** | Rokt pays them out to you in full via PayPal (or wire/ACH if set up), separately from the Aftersell discount. | ## How the matching discount is calculated Each billing cycle, Aftersell looks at your Rokt Thanks earnings from the **last 30 days** and adds a matching discount to your Aftersell bill, sized to match those earnings. The discount is capped at your bill amount, so it never exceeds what you would have paid. How this plays out depends on how much you earned in the last 30 days: | Last 30 days earnings | Matching discount | What you pay Aftersell | | :---------------------- | :----------------------- | :------------------------- | | **Exceed your bill** | Caps at your bill amount | **\$0** | | **Match your bill** | Covers the full bill | **\$0** | | **Less than your bill** | Matches your earnings | The remainder of your bill | Either way, your Rokt Thanks earnings continue to pay out to you in full. On your Aftersell admin (Settings → Billing), the matching discount shows the exact 30-day earning window it was sized to match, for example "May 5 to June 3 Rokt earnings". Hover the info icon next to the line for the full breakdown. If your plan bills more than one Aftersell charge (for example, a grandfathered Post-purchase and Checkout plan), the charges are billed together on the same day for Earn & Save merchants. The matching discount applies to the combined Aftersell bill, not to each charge separately. ## Am I eligible? Your store qualifies for Earn & Save if it processes **at least 1,000 orders per month**. Earn & Save applies to your total Aftersell bill, whatever plan you are on (current or grandfathered) and whichever features it includes. The matching discount applies to your full Aftersell charge each cycle. What you actually earn through Rokt Thanks depends on factors like your traffic, order volume, and offer relevance to your customers. Higher engagement generally leads to higher earnings. If your store does not currently meet the 1,000 monthly order threshold, you can still use Aftersell on a standard paid plan. Eligibility is re-evaluated continuously, so Earn & Save will surface in your admin if your store crosses the threshold later. ## Enrolling in Earn & Save The enrollment flow depends on your current Aftersell setup. Some stores see additional steps, others enroll in a single click. Some stores are required to confirm updated subscription terms before enrolling. You will see a prompt in your Aftersell admin if this applies to your store. If you do not see a prompt, skip to step 2. This typically applies to stores on an older Aftersell billing plan that includes the Checkout feature. Confirming the updated terms does not change your features or your base plan price. It only authorizes Aftersell to add the matching discount line to your future bills. Open the Rokt Thanks dashboard in your Aftersell admin and click **Enable**. Then place at least one Rokt Thanks app block on a customer-facing page. Your Thank You page is the recommended starting point. Completing both of these actions activates Rokt Thanks on your store and starts your Earn & Save discount. The setup guide on the dashboard tracks more than these two, though - it also asks for the block on your Order status page, and on your customer account Orders page if your store is eligible - so it stays marked **Incomplete** until those are placed too. If you need help with block placement, see Activating and Configuring Rokt Thanks. Setting up your payouts (PayPal or wire/ACH) is a separate step that is not required for Earn & Save to apply the matching discount to your bill. Payout setup only affects how you receive your Rokt Thanks earnings. See [Rokt Thanks Payouts](/aftersell/rokt_thanks_payouts) for details. ## Maximizing your earnings The more visible the Rokt Thanks block is on your store, the more opportunities your customers have to interact with offers. A few practical things you can do to increase visibility: **Place the block above the fold.** Buyers do not always scroll the confirmation page. Place the Rokt Thanks block in the **Main** section of your Thank You page, just below the order-confirmation banner, so it appears without scrolling. Avoid the Order Summary column and the Footer. **Add the block to multiple surfaces.** Rokt Thanks can render on up to four customer-facing pages: your Thank You page, your Order Status page, your customer account Profile page, and your customer account Orders page (if you are on Shopify's new customer accounts, also called Vaulted Rewards). Placing the block on all four surfaces can lift earnings by an estimated 10 to 20 percent on top of the Thank You page alone. See Rokt Vaulted Rewards. **Keep Rokt Thanks active.** The matching discount only applies while Rokt Thanks is active and generating earnings. If you disable or remove the Rokt Thanks block, earnings stop and the discount stops on the next cycle. You can re-enable anytime. ## What you see on your bill and payouts Earn & Save shows up in three places. Each handles a different part of the program. | | | | :-------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Shopify invoice** | Your Aftersell charge for the cycle, with the matching discount already applied. The charge can be as low as \$0 if the discount fully covers it. | | **PayPal (or wire/ACH)** | Your Rokt Thanks earnings, paid out by Rokt directly on their normal payout schedule (approximately 90 days after the end of the month the earnings were generated in). | | **Aftersell admin, Settings → Billing** | The current cycle's matching discount, the 30-day window it was sized to match, and your lifetime savings from the program. | ## Worked examples These examples use current plan pricing. Existing merchants are grandfathered on the plan and pricing they signed up under, so your own base fee and monthly cap may differ. Earn & Save works the same way on any plan. See [Aftersell billing & pricing](/aftersell/aftersell_billing_pricing) for the current plans. ### Scenario 1: matching discount covers part of the bill You are on the Post-purchase plan. Based on your order volume, your Aftersell bill for this cycle is \$149.99. Your Rokt Thanks earnings from the last 30 days are \$80. | | | | :---------------------------------- | :--------------------------------- | | Post-purchase charge | \$149.99 | | **Aftersell bill this cycle** | **\$149.99** | | Rokt Thanks earnings (last 30 days) | \$80 | | Matching discount added to bill | \$80 off (sized to match earnings) | | **What you pay Aftersell** | **\$69.99** | | **Earnings paid out to you** | **\$80** | The matching discount of \$80 is applied to your bill, leaving \$69.99 still due. You also receive your \$80 in Rokt Thanks earnings, paid out by Rokt directly. ### Scenario 2: matching discount covers the full bill You are on the Post-purchase plan. Your store is high-volume, doing 20,000 or more orders per month, which puts your Post-purchase charge at the maximum of \$999.99 (the highest the Post-purchase charge can reach, regardless of how high your order volume goes). Your Rokt Thanks earnings from the last 30 days are \$1,200. | | | | :---------------------------------- | :--------------------------------------------------- | | Post-purchase charge | \$999.99 (maximum) | | **Aftersell bill this cycle** | **\$999.99** | | Rokt Thanks earnings (last 30 days) | \$1,200 | | Matching discount added to bill | \$999.99 off (sized to earnings, capped at the bill) | | **What you pay Aftersell** | **\$0** | | **Earnings paid out to you** | **\$1,200** | Your earnings exceed your bill, so the matching discount caps at \$999.99 and your Aftersell charge for the cycle is \$0. You still receive your full \$1,200 in Rokt Thanks earnings, paid out by Rokt directly. The discount does not grow beyond your bill amount. ## Troubleshooting Yes. When your Rokt Thanks earnings from the last 30 days reach or exceed your bill amount, the matching discount covers the full bill and you pay \$0 for that cycle. You continue to receive your full earnings from Rokt Thanks, paid out separately. Whether your bill reaches \$0 depends on your earnings each cycle. It is possible, not guaranteed. The matching discount is sized to match your Rokt Thanks earnings from the last 30 days. If your earnings did not reach your bill amount, the discount is sized to match whatever you earned, and the remainder of the bill is still due. Your Rokt Thanks earnings continue to pay out to you in full. Only when your Rokt Thanks earnings consistently meet or exceed your Aftersell bill. If you earn \$50 in a 30-day period and your bill is \$349, your matching discount is \$50 and the remaining \$299 is still due. For high-volume stores with strong engagement, it is common for earnings to fully cover the bill each cycle. For smaller stores, Earn & Save is best thought of as a recurring savings on your subscription, not free service. The matching discount is capped at your bill amount, so the discount itself does not grow beyond that. Your earnings always pay out in full regardless, so you still receive everything Rokt Thanks earned for you during that cycle. Earnings and the discount are separate. A few common reasons: * **Rokt Thanks is not yet enabled or showing offers.** Open the **Rokt Thanks** tab in your Aftersell admin and check the setup guide there - it should show Rokt Thanks enabled and your app blocks placed. Settings → Billing gives you a quick read too: the Earn & Save card carries an **Active** / **Inactive** badge, and if your Thank you page block is missing it shows the nudge "Almost there, finish your Rokt Thanks setup to start earning a matching discount." The Rokt Thanks tab is still where you fix it. * **You have not earned yet.** The discount is sized to match your last 30 days of Rokt Thanks earnings. If you only just enabled Rokt Thanks, give it a billing cycle to start earning. * **You are still ramping up.** Earnings depend on traffic, order volume, and offer relevance. Results vary by store and grow over time. You stay enrolled in the program, but the matching discount only applies while Rokt Thanks is active and generating earnings. If you disable Rokt Thanks, the discount stops on the next cycle. You can turn Rokt Thanks back on anytime to resume. It depends on your current Aftersell billing plan. If you are on an older Aftersell plan that includes the Checkout feature, you may be prompted to confirm updated subscription terms when you enroll. Look for the Earn & Save prompt in your Aftersell admin. If you do not see a prompt, you can enroll without confirming any new terms. Earnings are paid out approximately 90 days after the end of the month the revenue was generated in. Payouts are also subject to a minimum threshold based on your payout method. Full details are on the [Rokt Thanks Payouts](/aftersell/rokt_thanks_payouts) page. The Earn & Save card is always accessible from your Aftersell admin under **Settings → Billing**, where **Start saving** appears on both the Earn & Save card and the billing summary. The card stays available as long as your store is eligible. You can also add a **View Earn & Save** shortcut to your home page: select the pencil icon on the [Quick actions](/aftersell/home/quick-actions) widget and tick it. It isn't one of the default actions, so it appears only once you add it. Earn & Save is only surfaced for stores that meet the eligibility threshold of 1,000 monthly orders. If you have recently crossed that threshold and do not see the program, reach out to support and we can confirm your eligibility status. Yes. The Earn & Save card on Settings → Billing shows your lifetime savings from the program, alongside the current cycle's matching discount. No. Earn & Save sits on top of whichever standard plan you are on. Your features, your base plan price, and your maximum monthly charge stay the same. The only difference is the matching discount that gets added to your bill. You can stop the matching discount in two ways: * **Disable Rokt Thanks.** Earnings stop, and the discount stops on the next cycle. You can re-enable anytime. * **Leave the program entirely.** Contact the Aftersell support team via in-app chat. Your standard plan billing resumes on the next cycle. ## Need help? * For program questions or setup issues, contact the Aftersell support team via in-app chat or email [support@aftersell.com](mailto:support@aftersell.com). * For Rokt Thanks payout-specific questions, see [Rokt Thanks Payouts](/aftersell/rokt_thanks_payouts). * Include your store URL and a brief description of the issue for faster help. ### Related pages * [What is Rokt Thanks?](/aftersell/what_is_rokt_thanks) * [Activating and Configuring Rokt Thanks](/aftersell/activating_and_configuring_rokt_thanks) * [Rokt Thanks Settings](/aftersell/rokt_thanks_settings) * [Rokt Thanks Payouts](/aftersell/rokt_thanks_payouts) * [Aftersell Billing & Pricing](/aftersell/aftersell_billing_pricing) # FAQ widget (Thank You Page) Source: https://docs.aftersell.com/aftersell/faq-widget-thank-you-page Configure the Thank You Page FAQ widget in Aftersell to answer common customer questions right after checkout. The FAQ widget displays common questions and answers on the Thank You page to reduce post-purchase support requests. This page covers every setting on the widget. For the full funnel setup and Shopify editor steps, see [How to configure thank-you page widgets](/aftersell/how_can_i_set_up_and_customize_thank_you_page_upsells_in_aftersell). Add the widget from the **Thank You Page** section of your funnel by clicking **Add Widget** and selecting **FAQs**. ## Add FAQ items 1. Click **Add FAQ Item**. 2. Enter your **question** text. 3. Enter your **answer** text. 4. Repeat for additional FAQ items. 5. Reorder items by dragging and dropping. 6. Click **Save**. # How to configure thank-you page widgets Source: https://docs.aftersell.com/aftersell/how_can_i_set_up_and_customize_thank_you_page_upsells_in_aftersell Step-by-step guide to setting up and configuring Thank You Page widgets in Aftersell Thank You Page (TYP) widgets in Aftersell are a powerful way to engage customers after a purchase and increase sales. This guide provides step-by-step instructions for configuring and enabling TYP widgets within your post-purchase funnels. TYP widgets work in conjunction with Post-Purchase offers, providing multiple opportunities to maximize customer conversions after checkout. *** ## What are Thank You Page widgets? Thank You Page widgets allow you to display additional content and product recommendations to customers immediately after checkout. They are highly customizable and do not face the same [Shopify limitations](/aftersell/why_isnt_my_1_click_offer_displaying) as post-purchase upsells. Thank You Page widgets enable you to: * Tailor offers to specific customer actions (funnel triggers) * Showcase personalized product recommendations * Engage customers in a non-intrusive way * Add [testimonials](/aftersell/thank_you_page_testimonials_widget), [FAQs](/aftersell/thank_you_page_faq_widget), [text content](/aftersell/thank_you_page_text_widget), and [images](/aftersell/thank_you_page_image_widget) to your Thank You page Each TYP widget is tied to a specific funnel, ensuring you retain flexibility and control for different customer journeys. *** ## Step-by-step setup guide ### Step 1: Create or select a funnel 1. Navigate to **Post-purchase Funnels** in your Aftersell admin. 2. Click **Add funnel**, then pick a template or choose to create one manually — or select an existing manual funnel. 3. Name your funnel (e.g., "Thank You Page Upsells - All Orders"). Thank You Page product recommendation widget previewing a snowboard upsell in the Shopify editor ### Step 2: Configure funnel triggers Define when your funnel should run. The triggers you set here apply to the entire funnel, including both Post-Purchase offers and Thank You Page widgets. Thank You Page widgets do not have separate trigger settings. Whatever triggers are configured for the funnel will also determine when the corresponding Thank You Page widgets display. 1. In the funnel settings, click **Triggers**. 2. Select trigger conditions based on: * Customer tags * Product purchased * Cart value * Order count * Collection * Discount codes used 3. Click **Save Triggers**. For step-by-step instructions on how to configure funnel triggers, including detailed targeting options and examples, refer to our [Funnel Triggers setup guide](/aftersell/how_to_configure_post_purchase_triggers). *** ### Step 3: Add TYP widgets to your funnel 1. Scroll to the **Thank You Page** section in your funnel. 2. Click **Edit extensions page** (or **Edit scripts page**, if your store has not yet migrated to Thank You page extensibility) to open the Thank You Page editor. 3. Pick a widget type from the sidebar and click **Enable** to turn it on. Every widget type already has its own tab — there is no separate "add" step. The available types are: * [**Product Recommendation**](/aftersell/thank_you_page_product_recommendation_widget) - Display upsell product recommendations * [**Testimonials**](/aftersell/thank_you_page_testimonials_widget) - Show customer reviews to build trust and social proof * [**FAQs**](/aftersell/thank_you_page_faq_widget) - Answer common customer questions * [**Text**](/aftersell/thank_you_page_text_widget) - Share messages, discount codes, or brand stories * [**Image**](/aftersell/thank_you_page_image_widget) - Display a custom image or banner * **Gift with purchase** - Offer a free gift alongside the order. This tab only appears once the feature has been enabled for your store; contact support if you would like it turned on. For the settings available on each widget type, see the individual widget pages linked above. *** ### Save your funnel configuration 1. Review all widget settings. 2. Click **Save Funnel** at the top of the page. 3. Set funnel status to **Active**. *** * **Max reviews to show** - How many reviews appear, from **1 to 3** (defaults to 3) * **Display type** - Choose between horizontal carousel or vertical stack layout * **Minimum rating** - Set the minimum star rating for reviews to display * **Truncate review text after (optional)** - Set a maximum character length for review text ## Enabling widgets in Shopify Widgets created in Aftersell must be added to your Thank You page or Order Status page in the Shopify editor, otherwise they will not display to customers. We recommend placing the app blocks on both pages. ### Step 1: Open Shopify editor 1. In your Aftersell admin, click **Open Shopify Editor**. 2. This opens the Shopify checkout customization editor. Callout pointing to the Open Shopify editor button above the product selection list Aftersell prompt with an Open Shopify editor button for placing widgets ### Step 2: Add widgets to the Thank You page 1. In the Shopify editor, navigate to **Thank You page**. 2. Click **Add app block** or **Add section**. 3. Select the Aftersell block matching the widget you configured. Each widget type is published as its own app block: **TY Product Recommendation Widget**, **TY Testimonials Widget**, **TY FAQs Widget**, **TY Text Widget**, **TY Image Widget**, or **TY Gift with Purchase**. 4. Position the widget block where you want it to appear. 5. Repeat steps 2-4 for every widget you enabled, one block each. 6. Click **Save**. Place your widget toward the top of the Thank You page for best visibility. Widgets positioned lower on the page may not be seen on all devices, particularly on mobile where customers are less likely to scroll. Shopify theme editor Add app block menu with the Aftersell Thank You widget selected on the Thank You page ### Step 3: Add widgets to the Order Status page Repeat the same steps on the **Order Status page** in the Shopify editor so customers who return to their order confirmation still see your widgets. Adding an Aftersell app block to the Shopify Order status page in the checkout editor ### Step 4: Publish your changes 1. Review the page in the preview. 2. Click **Publish** in the top-right corner. 3. Confirm the publication. Your TYP widgets are now live and will display to customers based on your funnel triggers. *** 1. Set the widget **Title** (it defaults to "FAQs"). 2. Click **Add FAQ**. 3. Enter your **question** text. 4. Enter your **answer** text. 5. Repeat for additional FAQ items. Each row has its own **Remove** button. 6. Click **Save**. ## Testing your widgets Shopify's checkout preview may not always display widgets correctly. Follow these steps to test: 1. **Set triggers to "Show for all customers"** (temporarily) to see widgets in preview. 2. **Place a test order** using a real checkout flow: * Use Shopify's test payment gateway * Create a free product for testing * Use a discount code to make the order \$0 3. **Verify widgets appear** on the Thank You page immediately after checkout. 4. **Test widget functionality:** * Click product recommendations * Verify checkout flow for upsells * Confirm order handling works as configured 5. **Reset triggers** to your desired targeting rules after testing. FAQ items appear in the order you add them, and **Add FAQ** always appends to the bottom — you cannot insert one part-way up the list. There is no drag-and-drop reordering either, so to move an item you have to remove everything from that position onward and re-add them in the order you want. *** ## Advanced configuration ### Combining with post-purchase upsells For maximum conversion, combine TYP widgets with post-purchase offers: 1. Add **Post-purchase Offers** to your funnel (before Thank You page). 2. Configure **TYP widgets** as a second touchpoint. 3. Customers who decline post-purchase offers will still see TYP widgets. 4. This creates multiple conversion opportunities in the customer journey. 5. Choose a **Select style** — **Plain text** or **Banner**. Choosing Banner reveals a **Select type of banner** option. 6. Enter your **Heading text** (optional). 7. Enter your **Content**. 8. Click **Save**. These are plain text fields, not a rich-text editor — there is no toolbar for bold, italics, lists, or links. Use the Banner style or an [Image widget](#configure-image-widgets) if you need more visual emphasis. *** ## Troubleshooting * Verify funnel status is set to **Active**. * Check that funnel triggers match your test order conditions. * Confirm widgets are enabled in the funnel configuration. * Ensure the widget block is added to the Thank You page in the Shopify editor and positioned toward the top of the page. * Customers sometimes skip the Thank You page if they close the browser immediately after purchase. * Ensure Thank You page offers are correctly set up in the Shopify editor. * Verify the widget block is positioned correctly on the page. *** ## Limitations Countdown timers are not available on the Thank You page. This is a Shopify platform restriction and cannot be changed within Aftersell. Each funnel's Thank You Page widgets must be customized individually. There is no option to standardize them across multiple funnels. This ensures all offers are specific to the triggers and customer behavior for each funnel. *** Countdown timers on the Thank You page product recommendation widget are off by default and are not available on every store. Once the feature is enabled for yours, the widget's banner section gains **Enable timer**, **Timer duration**, and **Timer start** (page load or order created) controls, and the remaining time is inserted wherever you place the `{TIMER}` placeholder in your banner text. Contact support if you would like it turned on. **Want to go further?** * [Post-Purchase Best Practices](/aftersell/best_practices) - tips to improve conversion across all your offers * [How to Configure Post-Purchase Offers](/aftersell/how_to_configure_post_purchase_triggers) - set up your full post-purchase funnel # How do I cancel my Aftersell subscription? Source: https://docs.aftersell.com/aftersell/how_do_i_cancel_my_aftersell_subscription Cancelling and unsubscribing from Aftersell This guide walks through how to cancel your Aftersell subscription. Cancelling Aftersell uninstalls the app from your Shopify store and ends your subscription. Your settings, funnels, widgets, and configurations are retained for up to 1 year, so you can restore them if you reinstall within that window. ## Before you cancel If you are considering cancelling, these alternatives may address what you are looking to solve: * **Reduce your bill with Earn & Save.** Eligible stores can lower their Aftersell subscription cost through the Rokt Thanks Earn & Save program. Your Rokt Thanks earnings pay out to you in full, and a matching discount is applied to your monthly bill up to your bill amount. See the Earn & Save Program page for details and eligibility. * **Contact support before cancelling.** If a specific issue is driving your decision, our support team may be able to resolve it. Reach us via in-app chat or email [support@aftersell.com](mailto:support@aftersell.com). ## How to cancel To cancel your Aftersell subscription and uninstall the app: In the Aftersell admin, navigate to **Settings → Billing**. On the **Current plan** card, click **Uninstall** in the row of buttons at the bottom of that card, beside **Compare plans** and **View pricing tiers**. A confirmation modal will open. (Don't scroll to the bottom of the page looking for it — the Payment history card renders below the Current plan card.) In the modal, select the reason or reasons that best describe why you are cancelling. Your answer helps the Aftersell team improve the product. Depending on the reason you select, additional questions may appear. Answering these is optional but appreciated. Use the "Something else" field to share any additional context you would like to provide. The Final invoice banner displays any pending usage charges that will appear on your next Shopify invoice. Review these before confirming. Click **Uninstall** to confirm. Your subscription is cancelled and the app is removed from your Shopify store in a single step. ## What happens after cancellation * **Your subscription** ends immediately. No new charges will be submitted for the upcoming billing cycle. * **Pending charges** that were already submitted to Shopify before cancellation will still be collected on your next Shopify invoice. To avoid charges for the next cycle, cancel at least one day before your next billing date. * **Your data** (settings, funnels, widgets, configurations) is retained for up to 1 year after cancellation. * **If you reinstall within 1 year**, your previous configuration is still there and there is no restore step to run — uninstalling never deletes your funnels, widgets, or settings. Onboarding asks you to accept a plan again, and everything else is waiting as you left it. After 1 year, data may be removed and a reinstall will start you on a fresh setup. * **Your theme stays clean.** Aftersell does not leave any code behind in your Shopify theme when uninstalled. All storefront integration runs through Shopify app embeds and app extensions, which Shopify removes automatically when the app is uninstalled. You do not need to manually edit theme files to clean up after cancellation. Shopify collects app charges on its own billing cycle, not on the day a charge is submitted. If you uninstall after a charge has been submitted for the current cycle, that charge will still be collected on the next Shopify invoice. For more on this timing, see the "Why was I billed after uninstalling?" section of the Aftersell Billing & Pricing page. ## Need help? For questions about cancellation, pending charges, or your final invoice, contact the Aftersell support team via in-app chat or email [support@aftersell.com](mailto:support@aftersell.com). ### Related pages * Aftersell Billing & Pricing * Earn & Save Program # How to configure checkout widgets Source: https://docs.aftersell.com/aftersell/how_to_configure_checkout_widgets Enable and place Aftersell checkout widgets in Shopify Plus: upsells, cart controls, rewards, trust badges, testimonials, notes, images, and text. This guide walks you through how to configure and place checkout widgets in Aftersell, from enabling widgets to optimizing placement in Shopify Checkout for maximum conversion rates.. **Note:** Checkout widgets are only available to Shopify Plus merchants due to Shopify's Checkout Extensibility API restrictions. *** ## Step 1: Enable your widget in Aftersell Before adding widgets to your checkout, you need to enable them in the Aftersell admin. 1. Navigate to the **Checkout** tab in your Aftersell admin 2. Select the widget type you want to configure ([Upsells](#upsells), [Cart Controls](#cart-controls), [Rewards,](#rewards) [Trust Badges,](#trust-badges) [Testimonials](#testimonials), [Notes](#notes), [Images](#images), or [Text](#text)) 3. Click **Create** to build a new widget or select an existing widget to edit 4. Configure your widget settings (see [Widget types and configuration](#widget-types-and-configuration) below) 5. Click the **Enable** toggle in the top right corner of the widget settings 6. For restricted or advanced upsells, make sure you enable custom triggers before proceeding *** ## Step 2: Open the Shopify Checkout Editor There are two ways to access the Shopify Checkout Editor: **Option 1: From Shopify Admin** 1. Go to **Settings** in your Shopify Admin 2. Click **Checkout** in the left navigation 3. Click **Customize** next to your desired checkout profile **Option 2: From Aftersell** 1. Click the **Open Shopify Checkout Editor** button in the bottom right of the Aftersell Checkout editor page 💡 **Tip:** Option 1 gives you more control over which checkout profile you're editing. We recommend testing on a draft version first before setting it live. Shopify admin home with the Settings link highlighted to open the checkout editor *** ## Step 3: Add the app block to your checkout 1. In the Shopify Checkout Editor, click **Add app block** 2. Select your desired Aftersell widget from the list of available widgets 3. Choose the correct placement for your widget (see [Available placements](#available-placements) below) 4. If you want your widgets to display in Shop Pay checkout, check the [**Include app block in Shop Pay**](/aftersell/show_checkout_widgets_in_shop_pay) option 5. Click **Save** in the top right corner Shopify Checkout Editor with an arrow pointing to the Add block button in the sidebar *** ## Step 4: Position your widget 1. Drag and drop the app block to your desired location within the selected placement area 2. Click **Save** in the top right corner Shopify Checkout Editor block list beside a live checkout preview showing Aftersell widgets *** ## Widget types and configuration ## Placements Placements are created in the Aftersell Checkout editor and allow you to run multiple widgets of the same type on the same checkout page. For example, if you want to display two upsell offers on the same page, each must be assigned to a different placement. ### Available placements * **Default placement**: The primary placement. Every widget type starts here. * **Additional placement 1**: A second placement slot for displaying another widget of the same type on the same page. * **Additional placement 2**: A third placement slot for further separation. You can also create new placements directly from the placement dropdown in Aftersell by selecting **+ Add new placement**. Aftersell Checkout editor showing the placement dropdown above the Upsells list and preview *** ### Placing a widget inside a shipping option row Most checkout widget types — Upsells, Rewards, Trust badges, Testimonials, Notes, Images, and Text — can be placed directly inside a shipping option row in the Shopify Checkout Editor. Cart Controls is the exception: it has no shipping-option target and cannot be placed in a row. When placed there, the widget renders inside the row for whichever shipping method the customer currently has selected. This lets you attach an offer or message to a specific shipping method — for example, showing an upsell or trust badge inside the selected shipping rate row. **How to set it up:** 1. Configure and enable your widget in the Aftersell admin as normal. 2. Open the Shopify Checkout Editor. 3. Click **Add app block** and select your Aftersell widget. 4. Drag the app block into the **Shipping** section of the checkout, placing it inside a shipping option row. 5. Select the matching placement (for example, **Default placement**) in the app block settings. 6. Click **Save**. **Things to keep in mind:** * The widget renders only inside the row for the shipping method the customer has selected. It does not appear in every row simultaneously. * The shipping section — and any widgets placed inside it — does not render for local pickup or digital-only carts. * Upsell widgets placed in a shipping option row can add products to the cart directly from inside the row. *** ### When to use multiple placements Use multiple placements when you want to: * Display more than one widget of the same type on a single checkout page * Show widgets in different sections of the page * Target different audiences with different offers * Run widgets with similar or overlapping triggers Aftersell uses a priority system. You cannot run multiple widgets with identical triggers within the same placement. If two widgets share the same trigger conditions in one placement, only one will display based on priority. To use similar triggers, assign each widget to a different placement so they can run independently without conflict. *** ## Matching placements in the Shopify Checkout Editor Each placement in Aftersell corresponds to a separate app block in the Shopify Checkout Editor. The placement selected in Shopify must match the placement set in Aftersell. For example, if a widget is assigned to **Additional placement 1** in Aftersell, the app block in Shopify must also be set to **Additional placement 1**. If placements do not match, the widget may not appear or may display in the wrong location. **Important:** A placement mismatch is one of the most common reasons a widget fails to display. If a widget is not appearing, confirm the placement matches in both Aftersell and Shopify before troubleshooting further. Shopify Checkout Editor Upsell Widget block settings with the Placement dropdown set to an additional placement *** ### Upsells Offer products to customers during checkout to increase your average order value (AOV). **Configuration options:** **Widget modes:** * **Single Product Upsell:** Display one product with an Add to Cart button * **Multi-Product Upsell:** Show multiple products in a stack or carousel layout, allowing customers to accept multiple offers * **Checkmark Upsell:** Display a single product with a checkbox instead of an Add to Cart button (ideal for low-cost add-ons like shipping protection) **Product selection methods:** * **Specific Products:** Manually select individual products to upsell * **Collection:** Select a collection and display up to 5 random products (products already in cart are automatically excluded) * **Automatic upsell(s):** Automatically recommend products based on cart contents * **Most Expensive Product:** Automatically upsell the most expensive product from the cart * **Spend threshold:** Recommend products that help customers reach reward thresholds (only selectable once **Show rewards bar** is enabled on the same upsell widget) * **Strategy:** Dynamically select a product using rule-based targeting. Only shown on stores with [Strategies](/aftersell/strategies_overview) enabled **Additional features:** * Add discounts directly within the widget * Lock subscription plans to specific options * Display product review stars (requires compatible review app) * Set a maximum number of accepted offers per widget (Single and Multi upsell types only) [Learn more about upsell widgets](/aftersell/checkout_widget_types#upsells) *** ### Cart Controls Allow customers to modify their cart directly on the checkout page. **Available controls:** * **Variant selector:** Change to another in-stock variant * **Quantity selector:** Adjust product quantities * **Remove item:** Show Remove Item Button removes upsell products from the cart. A paired setting, **Allow Removal of Non-Upsell Products** (off by default), extends removal to everything in the cart * **Subscription selector:** Change subscription frequency * **Subscription upgrade:** Upgrade one-time purchases to subscriptions * **Custom text:** Add custom text below line items **Product targeting:** * Apply to all products in cart * Apply only to selected products * Apply to all products except selected ones **Additional features:** * Display product review stars for in-cart products [Learn more about cart controls](/aftersell/checkout_widget_types#cart-controls) *** ### Rewards Display a progress bar showing customers how close they are to earning a reward. **Configuration options:** * Reward basis: **Cart total** or **Item count** * Amount basis (for Cart total): **Order total (includes shipping and tax)**, **Subtotal (before discounts)**, or **Subtotal after discounts (excludes tax and shipping)** * Reward message and styling * Progress bar colors and design **Best practices:** * Pair with upsell widgets to help customers reach reward thresholds * Use spend threshold product type in upsells to automatically recommend products that close the gap * Create rewards in Shopify using Automatic Discounts (for discount rewards) or Shipping Rules (for free shipping) * Use **Subtotal after discounts (excludes tax and shipping)** as the amount basis when offering free shipping, so the bar matches Shopify's own threshold evaluation when discount codes are applied [Learn more about rewards](/aftersell/checkout_widget_types#rewards) *** ### Trust Badges Build trust with custom icons and text to increase checkout conversion rates. **Configuration options:** * Badge layout: Vertical stack or horizontal display * Custom icons and text for each badge * Styling and spacing options **Best practices:** * Highlight security features (secure checkout, SSL encryption) * Showcase guarantees (money-back guarantee, free returns) * Display shipping benefits (free shipping, fast delivery) [Learn more about trust badges](/aftersell/checkout_widget_types#trust-badges) *** ### Testimonials Display customer reviews directly on checkout to build trust. **Configuration options:** * **Flex Testimonials (recommended):** Automatically pulls real reviews from your review app (Judge.me, Klaviyo, Okendo, or Yotpo) * Selection mode: Manual (choose specific reviews) or Dynamic (automatically fetch reviews based on cart contents) * Display type: Horizontal carousel or vertical stack * Minimum rating filter **Setup requirements:** * Configure review app credentials in Settings > Product Reviews * Reviews sync automatically within 24 hours, then weekly [Learn more about testimonials](/aftersell/checkout_widget_types#testimonials) *** ### Notes Allow customers to add notes to their order. **Configuration options:** * Manual notes: Free-text field for customer input * Pre-written notes: Checkboxes for options like gift wrapping or eco-packaging [Learn more about notes](/aftersell/checkout_widget_types#notes) *** ### Images Upload and display custom images in your checkout. **Configuration options:** * Image upload * Width adjustment slider * No minimum size requirement [Learn more about images](/aftersell/checkout_widget_types#images) *** ### Text Insert a banner with custom text in your checkout. **Configuration options:** * **Container Style:** **Plain Text** (the default) or **Badge**. The banner colors below only appear once you choose Badge * **Banner Type** (Badge only): * **Info (Blue):** Blue background with information icon * **Success (Green):** Green background with checkmark icon * **Warning (Yellow):** Yellow background with warning triangle icon * **Critical (Red):** Red background with exclamation point icon * Text size on the **Body** field (Small or Base) — the Heading field has no size control * Alignment on both the Heading and Body fields * Spacing: None, Extra Tight, Tight, Base, Loose, or Extra Loose [Learn more about text](/aftersell/checkout_widget_types#text) *** ## Troubleshooting ### Widgets not displaying If your widgets aren't showing after setup: 1. Verify widget is enabled in Aftersell admin 2. Check app block is added in Shopify Checkout Editor 3. Confirm app block is saved in Shopify Checkout Editor 4. Verify the correct placement is selected. When adding an app block in the Shopify Checkout Editor, you must choose the matching placement, such as Default placement, Additional placement 1, or Additional placement 2. If the wrong placement is selected, the widget may not appear or may display in the wrong location. Remove the app block and re-add it, ensuring the intended placement is selected. 5. For Shop Pay: Verify "Include app block in Shop Pay" is checked 6. Clear browser cache or try incognito mode 7. Wait a few minutes for changes to propagate ### Shop Pay widgets not showing To display widgets in Shop Pay checkout: 1. Open the widget in Shopify Checkout Editor 2. Check the **Include app block in Shop Pay** option under Checkout behaviour 3. Save your changes Shopify Checkout Editor sidebar showing the Aftersell Upsell Widget app block under Main [Learn more about Shop Pay Widgets](/aftersell/show_checkout_widgets_in_shop_pay) *** ## Next steps * [Learn about checkout triggers](/aftersell/checkout_triggers) to show widgets conditionally * [Set up checkout A/B testing](/aftersell/checkout_a_b_testing) to optimize placements * [Configure checkout branding](/aftersell/checkout_branding_settings) to match your store design * [Explore advanced upsell strategies](/aftersell/best_practices) to maximize AOV # How to install Rokt Thanks on Tapcart Source: https://docs.aftersell.com/aftersell/how_to_install_rokt_thanks_on_tapcart A Setup Guide for TapCart App Studio ## What is Rokt Thanks? Rokt Thanks displays personalized, non-intrusive offers to your customers on the post-purchase confirmation screen. It's a simple way to generate passive revenue from every order without impacting the customer experience. This guide walks through how to install Rokt Thanks within your TapCart mobile app using a Custom Code Block. The setup takes just a few minutes. ## Before you start You will need the following: * **TapCart Enterprise plan** - Custom Code Blocks are only available on Enterprise. If you're unsure about your plan, check with your TapCart account rep. * **Your Rokt Account ID** - your Aftersell account manager will provide this. If you don't have it yet, just reach out and we'll send it over. ## Step 1: Create a Custom Block Log in to your TapCart dashboard and open the App Studio editor. Create a new Custom Block. ## Step 2: Paste the code snippet In the Custom Block editor, switch to the Dev section. Clear any placeholder code and paste the snippet below: ```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} import * as React from "react" export default function RoktPlacement({ blockConfig, tapcartData, translations, pageState, useActions, }) { const containerRef = React.useRef(null) React.useEffect(() => { const loadRokt = async () => { try { await new Promise((resolve, reject) => { if (document.getElementById("rokt-launcher")) { resolve() return } const script = document.createElement("script") script.type = "text/javascript" script.src = "https://apps.rokt.com/wsdk/integrations/launcher.js" script.fetchPriority = "high" script.crossOrigin = "anonymous" script.async = true script.id = "rokt-launcher" script.addEventListener("load", () => resolve()) script.addEventListener("error", (error) => reject(error)) document.head.appendChild(script) }) const launcher = await window.Rokt.createLauncher({ accountId: "YOUR_ACCOUNT_ID", sandbox: true, }) await launcher.selectPlacements({ identifier: "TapCart.success", attributes: { email: tapcartData?.customer?.email || "", firstname: tapcartData?.customer?.firstName || "", lastname: tapcartData?.customer?.lastName || "", }, }) } catch (error) { console.error("Rokt SDK failed to load:", error) } } loadRokt() }, []) return
} ``` ### Replace Your Account ID In the snippet above, find the line `accountId: "YOUR_ACCOUNT_ID"` and replace `YOUR_ACCOUNT_ID` with the Account ID provided by your Aftersell account manager. Once updated, save the Custom Block. ## Step 3: Add to your Post Purchase page Navigate to your Post Purchase page in TapCart's visual editor. Drag the Custom Block you just created onto the page and drop it wherever you'd like the offers to appear. ## Step 4: Let us know Once you've completed the steps above, let your Aftersell account manager know. We'll finalize a quick configuration on our end and confirm when everything is live. The snippet is initially set to sandbox mode (`sandbox: true`), which loads test offers so you can preview the placement. `sandbox` is an option on the launcher in the snippet itself, not a setting on our side — so once we've confirmed everything looks right, edit the Custom Block, change `sandbox: true` to `sandbox: false`, and save. You'll start earning revenue from that point. ## Summary | Step | Action | | ---- | --------------------------------------------------------------------------------------------------- | | 1 | Create a Custom Block in TapCart's App Studio editor | | 2 | Paste the code snippet into the Dev section (replace `YOUR_ACCOUNT_ID` with your actual Account ID) | | 3 | Drag the Custom Block onto your Post Purchase page | | 4 | Notify your Aftersell account manager so we can finalize setup | ## Frequently asked questions **Do I need to be on TapCart Enterprise?** Yes. Custom Code Blocks in App Studio require TapCart's Enterprise plan. **Will this slow down my app?** No. The script loads asynchronously and won't block your page from rendering. **Can I choose where the offer appears on the page?** Absolutely. Once the Custom Block is saved, you can drag it to any position on your Post Purchase page using TapCart's visual editor. **What kind of offers will my customers see?** Rokt Thanks serves relevant, non-intrusive offers from premium advertisers tailored to each customer. # Image widget (Thank You Page) Source: https://docs.aftersell.com/aftersell/image-widget-thank-you-page Configure the Thank You Page Image widget in Aftersell to display a custom image or banner on the post-checkout page. The Image widget displays a custom image or banner on the Thank You page, useful for promotions, community links, or brand imagery. This page covers every setting on the widget. For the full funnel setup and Shopify editor steps, see [How to configure thank-you page widgets](/aftersell/how_can_i_set_up_and_customize_thank_you_page_upsells_in_aftersell). Add the widget from the **Thank You Page** section of your funnel by clicking **Add Widget** and selecting **Image**. ## Upload and size the image 1. Click the upload area to add your image. 2. Upload a JPG, PNG, or supported image file. 3. Adjust the **Image width** slider (50-500px) to control how large the image appears. 4. Click **Save**. # Checkout upsells Source: https://docs.aftersell.com/aftersell/implementing_strategies_checkout_upsells Use a Strategy to dynamically choose the product shown in a Shopify Plus checkout upsell widget. ## Overview When configuring a checkout upsell widget, you can fill the product slot in a few ways: hand-pick a specific product, let AI recommend one, or attach a **Strategy**. Each is a different tool for a different job. Strategies are for **dynamic merchandising in real time** - pairing the right accessory with a parent product, suggesting a complementary item, or surfacing a different product depending on what's already in the cart. Where checkout **triggers** decide *which* widget appears for a given shopper, a Strategy decides *what product goes inside it*. Triggers are the gateway, Strategies are the brain behind the experience. *** ## Attaching a Strategy to a Checkout Widget Strategies are attached **per widget**, not to the checkout as a whole. You can mix Strategy-driven widgets and static-product widgets in the same checkout. 1. Open the checkout widget you want to edit. 2. In the **Select product type** menu, choose **Strategy**. 3. In the Strategy picker, search for and select the Strategy you want to use. 4. Click **Confirm**, then save the widget. Once attached, the widget displays the Strategy's name in place of a specific product. Each time the checkout loads, the Strategy is evaluated and the returned product is rendered in the widget. Give your Strategies clear, descriptive names. The Strategy name is what shows up in the widget editor once attached, and it's the easiest way to know at a glance which Strategy is driving which widget. *** ## What the Strategy Sees Checkout has a **narrower context** than post-purchase. The Strategy is evaluated as the checkout page loads, before the order is placed - so customer history and session attribution aren't available yet. The following is what gets sent automatically: #### Product context The line items currently in the cart are sent as the input products. Triggers like **product tags**, **product collections**, **product type**, **vendor**, and **product metafields** all evaluate against these items. **Selling plan doesn't evaluate here.** Checkout line items don't carry a selling plan in this payload, so a **Selling plan** trigger never matches on checkout widgets. #### Cart context * **Subtotal** - the cart subtotal. * **Item count** - total quantity across all lines. * **Line count** - number of distinct line items. **Customer and session triggers won't match in checkout.** Customer tags, order count, country, locale, and UTM parameters are not part of the checkout payload. If a Strategy used in a checkout widget relies on these triggers, those rules will never fire, and only product- or cart-scoped rules (or the Catch all) will be able to return a product. *** ## What Happens When the Strategy Returns The product(s) returned by the Strategy **replace** the placeholder in the widget - they don't add to it. The shopper sees the widget as if you had hand-picked that product yourself. The widget fills its slots from the returned products in priority order, up to the number of offers the widget is configured to show. A single-offer widget uses the first returned product. *** ## When No Product Is Returned If no rules match and the Strategy returns no products, the widget is **not shown** to the shopper - the slot disappears entirely from the checkout. To keep your widget firing, configure a **Catch all** in the Strategy so there is always a fallback product to return. See the [Building Strategies](/aftersell/strategies_building_in_app) page for how to set up a Catch all. *** ## Evaluation Timing By default, a Strategy on a checkout widget is evaluated **once, when the checkout page loads**. The product chosen at page load remains the product shown, even if the shopper adds or removes items during checkout. If the widget has **flexible trigger re-checking** enabled, the Strategy is instead re-evaluated whenever the cart changes during checkout, and the widget updates to reflect the new cart - similar to how the [Upcart integration](/aftersell/implementing_strategies_upcart_upsells) behaves. Plan your rules around whichever mode the widget uses: a fixed snapshot at checkout load, or a live re-evaluation on every cart change. *** ## Tips for Checkout Strategies * **Design around products and cart only.** Customer- and session-scoped triggers will never match in checkout, so build Strategies around product attributes (tags, collections, metafields) and cart shape (subtotal, item count, line count). * **Use Catch all as a safety net.** A Strategy without a Catch all will hide the widget if nothing matches. A simple Catch all keeps the slot showing *something*. * **Mix dynamic and static widgets.** Not every widget has to be Strategy-driven. A common pattern is a Strategy on the primary upsell widget (most personalized) and a static product on a secondary widget (proven seller). # Custom integration Source: https://docs.aftersell.com/aftersell/implementing_strategies_custom_integration Call the Strategies API directly to power custom storefront experiences - PDP carousels, custom cart upsells, and anywhere else Aftersell's native surfaces don't reach. ## Overview When neither Aftersell's native surfaces (post-purchase, checkout, Upcart) nor a packaged integration fits, you can call the Strategies API yourself from your Shopify theme and render the returned products however you like. The pattern is the same in every case: build a context payload from Liquid (so Shopify attributes like the current product, cart contents, and customer fields are filled in at render time), `POST` it to `/api/public/strategy/evaluate`, and render the response. This page covers two implementation patterns: * **PDP context** - drop a section onto product pages that calls the API with the **currently-viewed product** and renders a carousel of returned recommendations. * **Cart context** - render an upsell block inside a custom cart that calls the API with **all current cart line items** and renders the returned products. The shape of the **product context** is what differs between the two: a single product on PDP, an array of all line items in cart. *** ## What You'll Need 1. **Your Strategy API key.** In Aftersell, go to **Settings → Product Strategy** and, in the **Security Token** card, copy your token (this is your Strategy API key). 2. **The Strategy ID.** Open the Strategy you want to run in the Aftersell Strategy editor and copy its ID. 3. **Theme code access.** You'll be adding a Liquid section (PDP) or block (custom cart) to your Shopify theme - Online Store → Themes → ... → Edit code. Your Strategy API key sits in client-side theme code, which makes it visible to anyone who views the page source. Treat it as a public storefront credential and rotate it from Aftersell **Settings → Product Strategy** if it's ever exposed in a way you didn't intend. *** ## PDP Context: Section Snippet This pattern adds a Shopify section to your product page. When the page renders, Liquid embeds the current product, cart, and customer attributes into the payload, then JavaScript posts to the Strategies API and renders the returned products in a Splide carousel. ### Installing 1. In your Shopify admin, go to **Online Store → Themes**, click **...** on your theme, and select **Edit code**. 2. Under the **Sections** folder, create a new file named `aftersell-upsell-carousel.liquid`. 3. Paste the snippet below into the new file and replace `YOUR_STRATEGY_API_KEY` with the API key from Aftersell. 4. Save. 5. Open your product template (typically `templates/product.json` or `sections/main-product.liquid`) and add the **Aftersell Carousel** section where you want the carousel to appear. From the theme editor, you can also drag it onto the product page directly. 6. In the section's settings, paste your **Strategy ID**. ### What the section sends For each PDP view, the payload includes: * **products** - a single-element array containing the currently-viewed product (productId, variantId, quantity, price, handle, title, vendor, productType, tags, collections, sellingPlan). * **cart** - subtotal, item count, line count of the shopper's current cart (omitted if the cart is empty). * **cartToken** - so the API can stitch this evaluation into the same session. * **customer** - tags, country, province, locale, order count, total spent, and accepts-marketing flag, but **only if the shopper is logged in**. * **session** - currency code from `shop.currency`. The section does not send UTM parameters by default. If you want UTM-based targeting on PDP, capture them client-side and add them to the `session` object before the fetch. ### The snippet ```liquid theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} {% comment %} Aftersell Carousel (Splide) Type: Section — save to sections/aftersell-upsell-carousel.liquid {% endcomment %} {% if product %} {% endif %} {% schema %} { "name": "Aftersell Carousel", "settings": [ { "type": "text", "id": "strategy_id", "label": "AfterSell Strategy ID", "default": "ADD_ID_HERE" }, { "type": "text", "id": "heading", "label": "Heading", "default": "You might also like" }, { "type": "text", "id": "cta_label", "label": "CTA Button Label", "default": "Add to cart" }, { "type": "range", "id": "max_products", "label": "Max Products to Show", "default": 8, "min": 1, "max": 20, "step": 1 } ], "presets": [{ "name": "Aftersell Carousel" }] } {% endschema %} ``` A Strategy-powered product carousel rendered on a Shopify product page ### Customizing The section schema exposes four merchant-editable settings: **Strategy ID**, **Heading**, **CTA Button Label**, and **Max Products to Show**. Add or remove settings in the `{% schema %}` block to expose more knobs to the theme editor. The CSS is scoped under `.aftersell-*` class names and includes a Splide-driven 4-up carousel that drops to 2-up at 768px and 1-up at 480px. Edit it freely to match your theme - none of it is required for the API call to work. *** ## Cart Context: Custom Cart Upsell Block This pattern is structurally the same as the PDP one, with one key difference: the **product context array** is built from the cart's line items instead of the currently-viewed product. The Strategy then receives every item the shopper has added and returns recommendations based on the cart as a whole. The implementation lives wherever your custom cart code lives - a Liquid section that renders the cart drawer, a custom block in a headless storefront, or a theme template like `cart.liquid`. The shape of the API call and the response handling are identical to the PDP example - only the `products` array differs. The structure looks like: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} var products = {{ cart.items | json }}.map(function(item) { return { productId: 'gid://shopify/Product/' + item.product_id, variantId: 'gid://shopify/ProductVariant/' + item.variant_id, quantity: item.quantity, price: item.price / 100 // ...other fields as needed }; }); ``` The rest of the payload (cart, customer, session, cartToken) and the `fetch` call to `/api/public/strategy/evaluate` are unchanged from the PDP pattern above - only the `products` array swaps from `[productContext]` to the cart-derived array. *** ## What Happens When the Strategy Returns The response shape is the same regardless of which context you sent: ```json theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} { "success": true, "products": [ /* enriched recommended products */ ], "evaluationId": "f3a1c2e0-...", "resolution": { "strategyId": "...", "matchedRuleIds": [...], "fallbackUsed": false }, "meta": { "servedFromCache": false, "processingTimeMs": 12, "data": {} } } ``` The `evaluationId` is a unique id for this evaluation. If you capture it and attach it to the products you render, you can attribute the resulting order back to the exact recommendation that produced it - see [Attribution](#attribution) below. How you render the `products` array is entirely up to your theme code. The PDP snippet above renders them as a carousel of cards with variant pickers and add-to-cart buttons; a custom cart block might render them as a vertical list inside the drawer. For the full request and response schema, see the [Evaluate Strategy API reference](/aftersell/strategies_api_reference_evaluate_strategy). *** ## When No Product Is Returned If the Strategy returns no products (`products: []`), it's up to your code how to handle it. The PDP snippet above hides the carousel entirely. A custom cart block might fall back to the cart's default upsell list, or simply render nothing. To avoid an empty response, configure a **Catch all** in the Strategy so there is always a fallback product to return. See the [Building Strategies](/aftersell/strategies_building_in_app) page for how to set up a Catch all. *** ## Tips for Custom Integrations * **Build context in Liquid.** Liquid runs at render time and has access to the full Shopify object graph - product, cart, customer, shop, request. Use it to populate the payload server-side rather than reaching for client-side calls. * **Keep the API key out of public repos.** It will end up in your theme code, which is shipped to the browser - that's fine. But don't paste the same theme into a public repository or share the bundle externally. * **Use a Catch all.** Storefront experiences look broken when a slot disappears. A Catch all with a small set of safe defaults keeps the UI consistent. * **Cache where it makes sense.** The Strategies API does light caching server-side (`meta.servedFromCache`), but for high-traffic PDPs you may also want to debounce or memoize calls on the client (e.g. don't re-call when the same product is rendered twice in a session). *** ## Attribution When a shopper clicks the add-to-cart button in the snippet, the `/cart/add.js` call attaches **line item properties** to the cart item: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} properties: { "_source": "Aftersell", "_attribution": "CTA" } ``` These properties travel with the line item all the way through to the Shopify order, where they appear on the line item record. You can use them downstream to attribute revenue, filter orders, or feed analytics tools that read line item properties. The keys and values are conventions, not requirements - the API call works the same regardless of what you put here. Change them to fit your own attribution model. For example: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} properties: { "_source": "PDP Carousel", "_strategy_id": "{{ section.settings.strategy_id }}", "_campaign": "summer-2026" } ``` Property keys that begin with an underscore (`_`) are hidden from the cart and checkout UI but still attach to the order. Use the underscore prefix for attribution-only metadata you don't want shoppers to see. Apply the same pattern in the cart-context implementation - any add-to-cart call you make from a custom upsell block can carry whatever properties you need. ### Attributing back to the evaluation To tie an order back to the **exact evaluation** that recommended the product - rather than just "came from a Strategy" - capture the `evaluationId` from the response and attach it to the line item under the `__as_offer_id` property. AfterSell reads this key, so orders tagged with it attribute to the specific evaluation in reporting. In the `evaluate()` handler, hold onto the id from the response: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} .then(function(data) { if (!data || !data.success || !data.products || !data.products.length) { clearSkeletons(); return; } evaluationId = data.evaluationId; // declare `var evaluationId;` alongside your other state renderCards(data.products.slice(0, MAX_PRODUCTS)); }) ``` Then include it in the add-to-cart properties: ```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} properties: Object.assign( { "_source": "Aftersell", "_attribution": "CTA" }, evaluationId ? { "__as_offer_id": evaluationId } : {} ) ``` Keep the double underscore on `__as_offer_id` - it's the key AfterSell looks for, and the underscore prefix keeps it hidden from shoppers. If `evaluationId` is absent (for example, no products were returned), skip the property rather than sending an empty value. # Post-purchase upsells Source: https://docs.aftersell.com/aftersell/implementing_strategies_post_purchase_upsells Use a Strategy to dynamically choose the product shown in a post-purchase upsell offer. ## Overview When configuring a post-purchase offer, you can fill the product slot in a few ways: hand-pick a specific product, let AI recommend one, or attach a **Strategy**. Each is a different tool for a different job. Strategies are for **dynamic merchandising in real time** - pairing the right accessory with a parent product, suggesting the next step in a routine, or surfacing a complementary item. Where triggers initiate a funnel + layout; a Strategy then decides what products go inside it. Triggers are the gateway, Strategies are the brain behind the experience. *** ## Attaching a Strategy to a post-purchase offer Strategies are attached **per offer step**, not to the funnel as a whole. You can mix strategy-driven steps and static-product steps in the same funnel. 1. Open the funnel you want to edit and go to the **Upsells** section. 2. On the upsell slot you want to configure, click **Create your first offer** (or **+** to add another offer). 3. Under **Select type**, choose **Single product upsell** or **Multi product upsell**. 4. Under **Select product type**, choose **Strategy**. 5. In the Strategy picker, search for and select the Strategy you want to use. 6. Click **Confirm**, then save the funnel. Selecting Strategy as the product type when creating a post-purchase upsell offer Once attached, the offer step displays the Strategy's name in place of a specific product. Each time the offer is shown, the Strategy is evaluated and the returned product is rendered. Give your Strategies clear, descriptive names. The Strategy name is what shows up in the funnel editor once attached, and it's the easiest way to know at a glance which Strategy is driving which offer step. *** ## What the Strategy sees When a post-purchase offer evaluates a Strategy, the following context is sent automatically. You don't need to configure any of it - it's pulled from the shopper's order and session as the offer is prepared. #### Product context The line items from the just-completed order are sent as the input products. Triggers like **product tags**, **product collections**, **product type**, **vendor**, and **product metafields** all evaluate against these items. **Selling plan doesn't evaluate here.** The order's line items don't carry a selling plan in this payload, so a **Selling plan** trigger never matches on post-purchase offers. #### Cart context * **Subtotal** - the order subtotal. * **Item count** - total quantity across all lines. * **Line count** - number of distinct line items. #### Customer context * **Customer tags** * **Order count** (lifetime orders for the customer) * **Country / province** * **Locale** Country, province, and locale are read from the order itself and are available for every checkout. Customer tags and order count come from the Shopify customer record - they populate as soon as the checkout is linked to a customer (which Shopify does once a recognized email is entered, or when a new customer record is created). #### Session context Post-purchase offers don't send a session context automatically - no landing URL, shipping, or store-currency data is included in the payload. **Marketing** and **Location** triggers (see [Building Strategies](/aftersell/strategies_building_in_app)) won't match on post-purchase offers unless you evaluate the Strategy yourself through a [custom integration](/aftersell/implementing_strategies_custom_integration) and supply that context. *** ## What happens when the Strategy returns The product(s) returned by the Strategy **replace** the placeholder in the offer step - they don't add to it. The shopper sees the offer as if you had hand-picked that product yourself. A single-product offer uses the first returned product. A multi-product offer fills its slots from the returned products in priority order. *** ## When no product is returned If no rules match and the Strategy returns no products, the post-purchase upsell is **not shown** to the shopper. To keep your funnel firing, configure a **Catch all** in the Strategy so there is always a fallback product to return. See the [Building Strategies](/aftersell/strategies_building_in_app) page for how to set up a Catch all. *** ## Tips for post-purchase Strategies * **Use Catch all as a safety net.** A Strategy without a Catch all will skip the offer step if nothing matches. A simple Catch all keeps the funnel showing *something*. * **Mix dynamic and static steps.** Not every step has to be Strategy-driven. A common pattern is a Strategy on the first offer (most personalized) and a static fallback offer on the second offer (proven seller). # Thank you page upsells Source: https://docs.aftersell.com/aftersell/implementing_strategies_thank_you_page_upsells Use a Strategy to dynamically choose the products shown in a Thank You Page product recommendation widget. ## Overview When configuring a Thank You Page **product recommendation** widget, you can fill it in a few ways: hand-pick specific products, return a collection, let AI recommend products, or attach a **Strategy**. Each is a different tool for a different job. Strategies are for **dynamic merchandising in real time** - pairing the right add-on with what the shopper just bought, surfacing a complementary item, or recommending the next step in a routine. Where the Thank You Page widget decides *where* recommendations appear, a Strategy decides *what products go inside it* - evaluated fresh against each order. A Strategy on the Thank You Page can also override each card's copy and apply a per-product discount, so different products can carry different messaging and pricing. See [Rule copy and per-product discounts](#rule-copy-and-per-product-discounts). *** ## Attaching a Strategy to a Thank You Page Widget A Strategy is the product source for a single product recommendation widget. It is **exclusive** - a widget sourced by a Strategy can't also use specific products, a collection, or AI recommendations. 1. Open the Thank You Page funnel and edit the **product recommendation** widget you want to configure. 2. In the **Add upsell products** menu, choose **Strategy**. 3. In the Strategy picker, search for and select the Strategy you want to use. 4. Confirm, then save the widget. Once attached, the widget shows the Strategy's name in place of specific products. Each time the Thank You Page loads, the Strategy is evaluated and the returned products are rendered in the widget. Give your Strategies clear, descriptive names. The Strategy name is what shows up in the widget editor once attached, and it's the easiest way to know at a glance which Strategy is driving which widget. *** ## What the Strategy Sees When a Thank You Page widget evaluates a Strategy, the following context is sent automatically. You don't need to configure any of it - it's pulled from the completed order and session as the page loads. #### Product context The line items from the **just-completed order** are sent as the input products. Product triggers - **product tags**, **product collections**, **product type**, **vendor**, **title**, **handle**, and **product metafields** - all evaluate against these items. Their attributes are resolved automatically, so you only need rules; you don't have to supply product data yourself. The products the shopper just bought are automatically **excluded** from the results, so a Strategy never re-recommends an item that's already in the order. #### Cart context * **Subtotal** - the order subtotal (in the store's major currency units, e.g. dollars). * **Item count** - total quantity across all lines. * **Line count** - number of distinct line items. #### Customer context * **Customer tags** * **Order count** (lifetime orders for the customer) * **Country / province** (the order's destination) * **Locale** #### Session context UTM parameters captured when the shopper arrived at the store: * **UTM source** * **UTM medium** * **UTM campaign** * **UTM content** * **UTM term** **Some triggers won't match on the Thank You Page.** Cart notes and cart attributes, customer total spent and accepts-marketing, the selling-plan trigger, and the shipping/store-currency triggers are not part of the Thank You Page payload. Rules that rely on these triggers will never fire here - build Thank You Page Strategies around product attributes, cart shape, customer tags / order count / location, and UTM parameters. *** ## Rule copy and per-product discounts A Strategy gives you per-product control over both the **copy** and the **discount** shown on each Thank You Page card. * **Rule copy** - a matching rule can set a **title**, **subtitle**, and **button (CTA) label** for the products it returns. When present, the rule's title appears above the product title (it doesn't replace it), the subtitle shows as a secondary line, and the CTA overrides the widget's button text. Cards whose products didn't come from a rule with copy render unchanged. * **Per-product discount** - a matching rule can set a discount (a percentage, or a fixed amount) that applies to the products it returns. This **overrides** the widget's configured discount, per product - so different rules can show different discounts on different cards. The discount shown on the card is the discount actually charged when the shopper accepts. The widget's own discount setting becomes the **default**: it applies to any returned product that the Strategy doesn't set a discount for. A **fixed-amount** discount in a currency other than the order's currency can't be applied, so the card falls back to the widget's configured discount instead. **Percentage** discounts always apply regardless of currency. *** ## What Happens When the Strategy Returns The widget renders the products the Strategy returns, in priority order, up to the widget's **maximum products to show**. Only products that are available for purchase are shown. The Strategy's products **replace** the widget's placeholder - the shopper sees the widget as if you had hand-picked those products yourself. *** ## When No Product Is Returned If the Strategy returns no products, the widget renders **nothing** - it's hidden from the Thank You Page. The page never breaks: if a Strategy can't be evaluated for any reason, the widget simply doesn't show. To keep the widget firing, configure a **Catch all** in the Strategy so there is always a fallback product to return. See the [Building Strategies](/aftersell/strategies_building_in_app) page for how to set up a Catch all. (Catch-all fallback products are shown without rule copy or a per-product discount.) *** ## Evaluation Timing A Strategy on a Thank You Page widget is evaluated **once, when the Thank You Page loads**. The order is already placed, so there's nothing to re-evaluate against - the products chosen at load are the products shown. *** ## How Shoppers Accept How an accepted upsell is processed depends on the funnel's order-handling setting: * **New order** - the shopper completes a separate, discounted checkout for the upsell product. * **Modify original order** - the upsell is merged into the order the shopper just placed. Either way, the product, variant, and discount are re-validated against what the Strategy returned before the order is created or edited - so the price charged always matches the price shown. *** ## Tips for Thank You Page Strategies * **Design around the order.** Product attributes (tags, collections, type, vendor, metafields), cart shape (subtotal, item/line count), customer tags / order count / location, and UTM parameters are the signals available here. * **Lean on copy and per-product discounts.** Use rule copy to tailor the pitch per product, and per-product discounts to vary pricing by rule - with the widget discount as a safe default. * **Use Catch all as a safety net.** Without one, the widget shows nothing whenever no rule matches. # Upcart upsells Source: https://docs.aftersell.com/aftersell/implementing_strategies_upcart_upsells Use a Strategy to dynamically choose the products shown in Upcart's upsells module. ## Overview Upcart is a separate app from Aftersell, so Strategies aren't baked into the Upsells module the way they are in Aftersell's post-purchase and checkout flows. Instead, you bridge the two apps with a small script that calls the Strategies API directly and feeds the result into Upcart's existing Upsells module via Upcart's public API. The script is **drop-in** - paste it once into Upcart's custom HTML, replace two values (your Strategy API key and the Strategy ID), and the Upsells module will start surfacing whatever products the Strategy returns. *** ## What You'll Need 1. **Your Strategy API key.** In Aftersell, go to **Settings → Product Strategy** and, in the **Security Token** card, copy your token (this is your Strategy API key). 2. **The Strategy ID.** Open the Strategy you want to run in the Aftersell Strategy editor and copy its ID. 3. **The Upsells module enabled in Upcart.** The script overrides the list of products shown in the existing upsell block, so the module needs to be turned on for anything to render. *** ## Adding the Script In Upcart, go to **Settings → Custom HTML → Scripts (before load)** and paste the script below. Replace `STRATEGY_ID` and `STRATEGY_API_KEY` with the values from Aftersell, then save. ```html theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} ``` Your Strategy API key authorizes calls against your shop's Strategies. The script above places it in client-side code, which is the only practical way to invoke the API from the cart drawer. Treat the key as you would any other public storefront credential and rotate it from Aftersell **Settings → Product Strategy** if it's ever exposed in a way you didn't intend. *** ## What the Strategy Sees Because this runs from the storefront cart, the context is a slim subset of what's available on Aftersell's native surfaces: #### Product context The line items currently in the Upcart cart are sent as the input products. Triggers like **product type**, **vendor**, **product handle**, **product title**, and any **product ID / variant ID** triggers all evaluate against these items. #### Cart context * **Subtotal** - cart subtotal in the store's major currency units (e.g. dollars). Upcart's `total_price` is in minor units (cents), so the script divides by 100 to match the units the rest of the Strategies API uses - and the units your `cart_subtotal` rules are authored in. * **Item count** - total quantity across all lines. * **Line count** - number of distinct line items. #### Session context * **Currency code** - taken from `window.Shopify.currency.active`. **Customer triggers and UTM triggers won't match.** The default script doesn't send customer tags, order count, location, or UTM parameters - so any rule using those triggers will never fire. Use product, cart, and currency triggers, or a Catch all, to make sure something always returns. *** ## What Happens When the Strategy Returns The products returned by the Strategy fully **replace** the list Upcart would otherwise show in the Upsells module. The merchant-defined upsell list is overridden for the duration of that cart - it's not merged in. Each Strategy product is mapped to Upcart's expected product shape (variants, images, options, metafields, etc.) so it renders inside the upsell block exactly like any other product. *** ## When No Product Is Returned If the Strategy returns no products, the Upsells module renders **empty** - no upsells are shown. To avoid this, configure a **Catch all** in the Strategy so there is always a fallback product to return. See the [Building Strategies](/aftersell/strategies_building_in_app) page for how to set up a Catch all. *** ## Re-Evaluation on Cart Changes Unlike checkout upsells, the Upcart implementation **re-evaluates the Strategy every time the cart changes** - items added, removed, or quantity-updated. The script subscribes to Upcart's `cartUpdated` event, sends the new cart to the Strategies API, and refreshes the cart drawer with the new upsell list. A cart-signature check skips redundant calls if the line items and quantities haven't actually changed, so back-to-back cart events that don't materially change the cart won't re-hit the API. *** ## Tips for Upcart Strategies * **Design around the cart.** Cart-shape and product triggers are the strongest signals you have here. Customer history and UTM-based targeting aren't sent by the default script. * **Use Catch all as a safety net.** Without one, the Upsells module will show nothing whenever no rule matches. * **Cache-friendly by default.** The cart-signature guard prevents re-firing the API if the cart hasn't materially changed - good for shoppers who toggle the cart open and closed without editing it. # Aftersell & Judge.me reviews integration Source: https://docs.aftersell.com/aftersell/judgeme_reviews_integration This article explains how to set up the Aftersell and Judge.me Reviews integration for the testimonials widget. Judge.me reviews work automatically with Aftersell for displaying review stars on upsell offers. To use Judge.me reviews in the testimonials widget, you need to provide your API key. ## Setting up Judge.me integration 1. Install the [Judge.me app](https://apps.shopify.com/judgeme) from the Shopify app store 2. In your Judge.me app, go to `Settings > Integrations > API token` 3. Copy your **Private API token** 4. Open the Aftersell app, then go to `Settings > Product Reviews` 5. Select **Judge.me** from the review integrations list 6. Paste your Private API token in the **Judge.me API key** field 7. Click **Save changes** The integration is complete. You can now use Judge.me reviews in your Testimonials widget. ## Syncing reviews Aftersell imports reviews from Judge.me and stores them so they can be displayed in the testimonials widget. **Saving your credentials doesn't start an import on its own.** The weekly automatic sync only picks up stores that have a **live Testimonials widget** whose selection mode is **Dynamic** and whose provider is Judge.me — on Checkout, on the Thank You Page, or in a post-purchase offer. Until such a widget exists, use **Sync now** below to import manually. Once you do have a qualifying widget, Aftersell re-imports that store's reviews about once a week. To import reviews immediately: 1. Go to `Settings > Product Reviews` 2. Find the **Judge.me reviews** section 3. Click **Sync now** The sync status shows when reviews were last imported and when the next sync is available. # Aftersell & Klaviyo reviews integration Source: https://docs.aftersell.com/aftersell/klaviyo_reviews_integration This article explains how to set up the Aftersell and Klaviyo Reviews integration for the testimonials widget. To use Klaviyo reviews in the Aftersell testimonials widget, you need to provide your Klaviyo private API key. ## Setting up Klaviyo integration 1. In Klaviyo, navigate to your account settings 2. Go to `Integrations > Developers > Manage API keys` 3. Click **Create Private API Key** * You can name it "Aftersell API key" * Select **read-only** permissions 4. Copy the generated API key 5. Open the Aftersell app, then go to `Settings > Product Reviews` 6. Select **Klaviyo** from the review integrations list 7. Paste your private API key in the **Klaviyo private API key** field 8. Click **Save changes** The integration is complete. You can now use Klaviyo reviews in your Testimonials widget. ## Syncing reviews Aftersell imports reviews from Klaviyo and stores them so they can be displayed in the testimonials widget. **Saving your credentials doesn't start an import on its own.** The weekly automatic sync only picks up stores that have a **live Testimonials widget** whose selection mode is **Dynamic** and whose provider is Klaviyo — on Checkout, on the Thank You Page, or in a post-purchase offer. Until such a widget exists, use **Sync now** below to import manually. Once you do have a qualifying widget, Aftersell re-imports that store's reviews about once a week. To import reviews immediately: 1. Go to `Settings > Product Reviews` 2. Find the **Klaviyo reviews** section 3. Click **Sync now** The sync status shows when reviews were last imported and when the next sync is available. # Managing checkout discounts Source: https://docs.aftersell.com/aftersell/managing_checkout_discounts Learn how to view, edit, and delete discounts created for checkout upsells in Aftersell The discount library in Aftersell allows you to manage all discounts created for your checkout upsells. You can view which upsells use each discount, edit discount details, and delete unused discounts. ## Accessing the discount library To access your discount library: 1. Open the **Aftersell** app in your Shopify Admin 2. Navigate to **Checkout** > **Discounts** The discount library displays all discounts you've created through Aftersell. These discounts also appear under "Aftersell Discounts" on your Shopify Discounts page. ## Understanding discount status The Checkout discounts page shows one status badge in the top right, reflecting whether your Aftersell checkout discount code is active on Shopify. It is a page-level status, not a per-discount one: * **Active on Shopify** - The discount is active and working correctly * **Inactive on Shopify** - The discount may be missing or deactivated on your Shopify Discounts page If a discount shows as inactive, check your Shopify Admin > Discounts page to verify the discount exists and is active. ## Editing a discount To edit an existing discount: 1. Click on the discount you want to edit from the list 2. The discount details appear in the right panel 3. Modify the **title**, **discount type** (percentage or fixed amount), or **amount** 4. Click **Update** to apply your changes ⚠️ Changes apply to all upsells using this discount. The "Used in" section shows which widgets and products currently use the discount. ## Deleting a single discount To delete a discount: 1. Click on the discount you want to delete 2. Click the **Delete** button in the right panel 3. Confirm the deletion in the modal The discount is removed from all upsells that use it. This action cannot be undone. ## Bulk deleting unused discounts If you have discounts that aren't currently used in any upsells, you can delete them all at once: 1. In the discount library, look for the **Delete X unused discount(s)** button 2. Click the button to see a list of all unused discounts 3. Review the list in the confirmation modal 4. Click **Delete X discount(s)** to confirm This feature only appears when you have unused discounts. The system automatically identifies which discounts aren't applied to any upsell offers. ## Searching discounts Use the search bar at the top of the discount library to find discounts by name. The search matches the displayed rule name, which is the title plus the savings amount — for example "Summer add-on (15% off)". Checkout discount rules do not have discount codes of their own, so you cannot search by code. ## Creating new discounts Discounts are created when you add them to upsell offers in the Checkout editor. You cannot create standalone discounts in the discount library. To create a new discount: 1. Go to **Checkout** > **Editor** 2. Edit or create an upsell widget 3. Click **Add discount** when configuring an offer 4. Choose **Create new** and set the title and amount The new discount appears in your discount library and can be reused in other upsells by selecting **Pick existing** when adding discounts. ## Related articles * [Checkout widget types](/aftersell/checkout_widget_types) - Learn about adding discounts to upsell widgets * [Creating your first checkout widget](/aftersell/creating_your_first_checkout_widget) - Step-by-step guide to creating checkout widgets # Connect your AI client with Aftersell MCP Source: https://docs.aftersell.com/aftersell/mcp-connect-self Connect an AI client like Claude Desktop to your store's Aftersell analytics using the Aftersell MCP server (Model Context Protocol). MCP (Model Context Protocol) is an open standard that lets an AI client read data from outside tools. Aftersell hosts an MCP server that gives your AI client read-only access to your store's Aftersell analytics. The self-serve connect page lets you link an AI client — such as Claude Desktop — to your store's Aftersell analytics. Once connected, you can ask your AI client questions about your store's upsell performance, funnel results, and more, directly in natural language. The connection is read-only: your AI client can read your Aftersell analytics data but cannot place orders or change any settings. Personally identifiable customer fields are blocked. ## What you can ask Once connected, you can ask your AI client questions like: * How much extra revenue did my upsells make last week? * How do I stack up against similar stores on post-purchase performance? * How are my funnels performing this week? * Break down my offer responses - how many were accepted, declined, or timed out? * Why aren't my post-purchase offers showing to more shoppers? * Which upsell products drove the most revenue last month? * Which of my active funnels is underperforming on conversions? * How many orders did my store get each day this month, and what was my average order value? * Compare my primary offer step vs the second offer vs the downsell - which converts best? * Is my upsell conversion rate trending up or down lately? * How many people saw my post-purchase offers each day over the last two weeks? * How does my revenue per visitor compare to similar stores? * Trace order #1234 - did the shopper see an offer? ## Connecting your AI client The connect page opens with **Choose your AI client**, a picker offering **Claude Desktop**, **Claude Code**, **Codex App**, and **Codex CLI**. The steps below it change to match your choice: Claude Desktop and Codex App give you a connector URL to paste into the client's own settings, while Claude Code and Codex CLI give you a single terminal command to copy instead. The walkthrough below is for Claude Desktop. 1. On the connect page, choose **Claude Desktop**. A single-use connect code is minted for you automatically and shown under step 3, **Enter the connect code** — you do not have to click anything to get one. It expires **6 hours** after it is generated; **Regenerate** gives you a fresh one, and **Generate** appears instead if no code is currently shown. 2. Copy the **Remote MCP server URL** from step 2, **Add the connector to Claude Desktop**. It is shown whether or not a code has been generated. 3. In Claude Desktop, open **Settings**, then **Connectors**. 4. Choose **Add custom connector** and paste in the URL. 5. Click **Connect**. Claude will ask for a connect code. 6. Enter the connect code from step 1. 7. A verification number appears in both Claude and your Aftersell admin. Select the matching number in your admin to approve the connection. Once approved, your status changes to **Connected** and you can start asking questions. ## Connecting a second store Your MCP connection is tied to your email address, not a single store. Once you have a connection set up, you can link additional stores without going through the full setup again. To link another store: 1. Open the connect page from that store's Aftersell admin. 2. The page shows a **Store data access** section with a **Link store** button. 3. Click **Link store**. The store is linked immediately — no connect code or approval needed. Once linked, your AI client can read that store's Aftersell data through the same connection. If you have more than one store linked, tell your AI client which store you're asking about. ## The two sections on the connect page The connect page has two independent sections: * **MCP connection** — the status of your AI client's connection to Aftersell MCP. This is email-global: one connection reaches every store you've linked. * **Store data access** — whether this specific store's data is accessible through your connection. The store data access section only appears once your MCP connection is active. ## Connection statuses ### MCP connection | Status | Meaning | | -------------------------- | -------------------------------------------------------------------------------------------------------------------- | | **Not connected** | No active MCP connection. Follow the setup steps to connect. | | **Awaiting your approval** | You've entered the connect code in your AI client. Select the matching verification number in your admin to approve. | | **Connecting…** | Your approval was submitted. The AI client is finishing the connection. This usually takes a few seconds. | | **Connected** | Your AI client is connected and can read your Aftersell analytics. | If your connect code or a pending approval lapses before the connection completes, the status stays **Not connected** — there is no separate expired status. Generate a new code and run through the steps again. ### Store data access Unlike the MCP connection section above, this section shows a status badge in one case only — **Expired**. The other states are shown in different ways: | State | What appears | Meaning | | ------------------ | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | | **Linked** | A **Linked** button with a checkmark — no badge | This store's data is accessible through your MCP connection. | | **Expired** | An **Expired** badge and a **Link store** button | This store's access lapsed after 30 days without use. Click **Link store** to restore it. | | **Not yet linked** | No badge — just the section description and a **Link store** button | Your connection exists but this store hasn't been linked yet. | | **Access removed** | No badge — a warning banner | A store owner or staff member removed this store's access. Ask them to restore it. | ## Disconnecting To disconnect your AI client from Aftersell MCP, click **Disconnect** on the connect page and confirm. This disconnects your AI client from all stores immediately. Your store access records are kept, so you can reconnect anytime by following the setup steps again. ## Who can connect Store owners, staff members, and collaborators can all self-connect. Collaborators connect and link stores for their own email address, scoped to the store they have a session for. Managing other people's MCP access — granting, approving, or revoking access for others — is limited to store owners and staff members. Access management is also rolled out separately from self-connecting, so the management screen may not be available on your store yet even though you can connect your own AI client. Contact the customer support team if you need it. ## Frequently asked questions **What is an MCP?** MCP (Model Context Protocol) is an open standard that lets an AI client connect to outside tools and data. This connector uses it to give your AI client read-only access to your store's Aftersell analytics. **What can the AI access?** Only your store's Aftersell analytics. Aftersell doesn't hold a full copy of your store's data, so the AI can't see everything in Shopify — just the analytics Aftersell has, scoped to this shop. It's read-only and personally identifiable customer fields are blocked. **My AI is asking me to approve tool calls. What does that mean?** AI clients ask for your approval before they run a tool, so you stay in control of what they do. When your AI wants to read your Aftersell data, it asks to call this connector's tools. Approve them to let it answer. It's read-only, so approving only lets the AI read your analytics; it can't place orders or change anything in your store. **Is my data safe?** Yes. The connector is read-only and scoped to your store's Aftersell analytics only. The verification number step during setup ensures only you can approve a connection. **How do I connect another store?** Open the connect page from each store's Aftersell admin and click **Link store** to give your connection access. Your MCP connection reaches every store you've linked, so when you have more than one, tell your AI client which store you're asking about. **My connect code expired. What do I do?** Generate a new code on this page and use that one. Each new code replaces the previous unused one. **How do I stop the AI's access?** Click **Disconnect** on this page to disconnect your AI client from Aftersell MCP right away. You can connect again anytime by following the setup steps. **Can I have multiple AI clients connected?** Each connect code is single-use. To connect a second device or client, generate a new connect code and repeat the setup steps. # Aftersell & Okendo reviews integration Source: https://docs.aftersell.com/aftersell/okendo_reviews_integration This article explains how to set up the Aftersell and Okendo Reviews integration for the testimonials widget. Okendo reviews work automatically with Aftersell for displaying review stars on upsell offers. To use Okendo reviews in the testimonials widget, you need to provide your User ID. ## Setting up Okendo integration 1. Install the [Okendo app](https://apps.shopify.com/okendo-reviews) from the Shopify app store 2. In your Shopify admin, open the Okendo platform 3. Go to `Settings > Integrations > Credentials` 4. Copy your **User ID** 5. Open the Aftersell app, then go to `Settings > Product Reviews` 6. Select **Okendo** from the review integrations list 7. Paste your User ID in the **Okendo User ID** field 8. Click **Save changes** The integration is complete. You can now use Okendo reviews in your Testimonials widget. ## Syncing reviews Aftersell imports reviews from Okendo and stores them so they can be displayed in the testimonials widget. **Saving your credentials doesn't start an import on its own.** The weekly automatic sync only picks up stores that have a **live Testimonials widget** whose selection mode is **Dynamic** and whose provider is Okendo — on Checkout, on the Thank You Page, or in a post-purchase offer. Until such a widget exists, use **Sync now** below to import manually. Once you do have a qualifying widget, Aftersell re-imports that store's reviews about once a week. To import reviews immediately: 1. Go to `Settings > Product Reviews` 2. Find the **Okendo reviews** section 3. Click **Sync now** The sync status shows when reviews were last imported and when the next sync is available. # Order browser troubleshooting Source: https://docs.aftersell.com/aftersell/order-browser-troubleshooting Fix common issues with offer statuses, funnel gaps, and ineligible orders in the Order Browser. Use this guide to investigate unexpected statuses or gaps you're seeing in the [Order Browser](/aftersell/order_browser_overview). If your offer isn't showing up at all before you even get to the Order Browser, start with [Why isn't my post-purchase offer displaying?](/aftersell/why_isnt_my_1_click_offer_displaying) or [Widget Not Displaying on the Thank You Page](/aftersell/widget_not_displaying_on_the_thank_you_page). For a complete overview of all Order Browser statuses, see the [Order Browser Overview.](/aftersell/order_browser_overview) Use this guide when you're investigating a specific status or unexpected gap. ## Why are so many orders showing as Ineligible? Ineligible orders are controlled entirely by Shopify, not Aftersell. The most common causes are unsupported payment methods (digital wallets, BNPL, full gift card), orders under \$0.50, multi-currency, and duties or landed costs. To investigate: use the **Ineligibility reason filter** in the order table to group orders by the specific reason. Then click into an individual order to confirm the payment method or order details behind it. For a full breakdown of every ineligibility reason and what to do about each one, see the [Order Browser Overview](/aftersell/order_browser_overview). For supported and unsupported payment methods specifically, see [Payment Methods](/aftersell/payment_methods). > **Tip:** If a large share of your orders are ineligible due to payment method, setting up [Thank You Page upsells](/aftersell/how_can_i_set_up_and_customize_thank_you_page_upsells_in_aftersell) is the best way to recover that traffic since TYP is not subject to Shopify's post-purchase restrictions. *** ## What does "Not configured" mean? Not configured means a funnel has an offer slot (e.g., Offer 2) that exists but has no offer set up in it yet. Order Browser rows showing Not configured status badges on empty offer slots To fix it: click the **PPU Funnel** link in the order table to go directly to that funnel, then add an offer to the empty slot. *** ## What does "Products excluded" mean and how do I fix it? Products excluded on a PPU offer slot means every product in your offer was excluded at the time of that order. Click into the order and open the PPU tab, the timeline will show a Products excluded warning with the specific reason listed below. * **Product already in order:** the offer product was already in the customer's cart. Turn off "Hide offer if already purchased" in your offer settings, or add different products to the offer. * **Product OOS:** the offer product was out of stock. Add more products so there's always something available to show. * **Product Inactive:** the offer product was unpublished or deactivated in Shopify. Republish the product or swap it for an active one. * **All products filtered:** every product was excluded by a combination of rules. Review your offer's filter settings and expand the eligible product pool. > **Tip:** To reduce this over time, add more products to each offer as fallbacks and periodically check that your offer products are in stock and published. *** ## A lot of orders are showing No interaction. What can I do? No interaction means the offer was shown but the customer left without clicking Accept or Decline. Some of this is normal behavior, but a consistently high rate can point to offer design issues. A few things that help: * **Fewer products per offer.** More than four items in a single offer can cause decision paralysis. Keep it focused and relevant to what the customer just bought. * **Enable Require Confirmation Click to Accept** in your offer settings. This makes the Accept/Decline action more intentional and typically drives cleaner conversion data. * **Check offer relevance.** If the offer doesn't feel connected to the original purchase, customers are more likely to ignore it. **Note on fulfillment holds:** When an order shows 'No interaction', a fulfillment hold is placed for up to 60 minutes. The hold lifts when the customer accepts, declines, or the session closes. See the [Fulfillment](/aftersell/fulfillment) doc for more detail. *** ## Orders are showing Customer skipped. Is something broken? Not necessarily. Customer skipped means the customer closed their browser or left before the post-purchase page had a chance to load. Common causes: * The customer navigated away immediately after checkout * The browser was closed before the post-purchase redirect completed * The checkout completed through an accelerated flow that bypassed the post-purchase step If you're seeing an unusually high volume of skips, check whether there have been any recent changes to your checkout configuration, or whether a specific sales channel is generating more skips than others. *** ## PPU Funnel is showing "No funnel triggered." How do I fix it? No funnel triggered means the order was eligible but no funnel matched its trigger conditions. Common causes: * No funnel has a trigger set to "All orders" as a catch-all fallback * Funnel trigger conditions (product tags, customer tags, order value) no longer match the incoming orders * Multiple funnels are competing and the expected one lost priority To fix this long-term: make sure you have at least one low-priority funnel with a trigger set to all orders so there's always a fallback. Click the **PPU Funnel** link in the order table (or the **Funnel triggered** event in the order timeline) to review and update your trigger logic directly. Order detail Post Purchase section showing a No funnel triggered warning *** ## The Improvement Opportunities panel is flagging gaps. What should I do? **Funnel & Offer opportunities** means one or more of your funnels has an unconfigured or missing offer slot. Use the Offer opportunities filter in the order table to find the specific orders, then click through to the funnel to set up the missing offer. **Product opportunities** means an offer is configured but its products are frequently being filtered out or are unavailable. Use the Product opportunities filter to surface those orders, review which products are causing the gap, and either replace them or loosen the filter settings. *** ## I'm seeing "Timer expired" on PPU offers Timer expired means the post-purchase session clock ran out while the offer was on screen. Shopify's post-purchase page has a time limit, and if the customer was on the page too long without interacting, the session expires. This is expected for a small percentage of orders. If you're seeing it frequently, check whether your offer has an unusually large number of products or steps that might be slowing down load or review time. *** ## My test order's PPU timeline is empty or incomplete If you placed a test order and the PPU tab shows no events or partial data, it's likely because the order ID wasn't available when the earliest events fired. This resolves automatically as the order completes - give it a few minutes and refresh. *** ## The PPU timeline is showing "Technical issue" Technical issue means the post-purchase experience failed to load for this order. This is different from Ineligible (where Shopify blocked it) — the session started but something prevented the page from rendering. "Not loaded" is a **Rokt Thanks** status only. It never appears on the PPU timeline, where the same underlying condition is reported as Technical issue. Common causes include browser issues on the customer's side, a network interruption mid-redirect, or a transient Shopify platform error. It is not typically caused by your Aftersell configuration. If you're seeing Not loaded on a small number of orders, no action is needed. If you're seeing it consistently across many orders, contact support and share the order numbers so the team can investigate whether there's a platform-level issue. *** ## I'm seeing "Shopify skipped" - what does that mean? Shopify skipped means Shopify bypassed the post-purchase page for this order at a platform level. When you click into the order and open the PPU tab, you'll see: > Shopify skipped can occur in a wider range of situations than just extreme platform load - including on development stores. If you're testing on a dev store and seeing this status, that is expected behavior. If you're seeing it at high volume on a live store with no clear cause, raise it with Shopify directly as it may indicate a Shopify platform issue. Order detail showing an ineligible post-purchase offer skipped by Shopify restrictions Before reaching out to Shopify, use the **Ineligibility reason** filter in the Order Browser and select **Skipped by Shopify** to isolate only those orders. Many ineligible orders have a clear reason (payment method, duties, minimum order value, etc.) that can be resolved without involving Shopify at all. Only orders specifically tagged Shopify skipped are ones where Aftersell has no visibility and Shopify needs to be contacted. Once you've confirmed the orders are genuinely Shopify skipped, use the **See Shopify docs** button in the order detail view or contact Shopify support directly for further context. *** ## I'm seeing "Pending conversion" on TYP widget Pending conversion means the Thank You Page offer was displayed but a final decision hasn't been recorded yet. The most common cause is that the page is still open in the customer's browser. It typically resolves to Accepted or No interaction once the session closes. If you're seeing a persistent volume that never resolves, reach out to support. *** ## I'm seeing "No products found" on TYP widget No products found means the Thank You Page experience couldn't load any products to display. This is different from Products filtered out (where products exist but were excluded by a rule), Out of stock / unavailable (where variants were returned but all are unavailable), and Selected variant unavailable (where a configured variant no longer resolves from Shopify). No products found usually points to a configuration issue with the TYP offer itself, such as all products being unpublished or unavailable. To fix it: review your TYP offer product selection and make sure at least one product is published and in stock. *** ## I'm seeing "Technical issue" on TYP widget Technical issue means there was a problem loading the Thank You Page experience for that order. This appears as a badge in the TYP tab of the order detail view. Like Not loaded on PPU, this is usually caused by a transient rendering or platform error rather than a configuration issue. If it's affecting a small number of orders, no action is needed. If you're seeing it consistently, reach out to support with the affected order numbers. *** ## Order Browser shows "no products recommended" for a Smart Funnel order If an order that ran through [Smart Funnel](/aftersell/smart_funnel) is showing no products in the Order Browser, the AI had no eligible candidates to display at the time the offer fired. Smart Funnel does not have its own product catalog — it pulls candidates from the recommendation source you have configured under **Settings → Automatic Upsells**, then applies Shopify eligibility and your exclusion rules on top. Common causes: * **All candidate products were filtered out.** Any SKUs you have excluded under **Settings → Automatic Upsells** are removed from the pool. If your exclusion list is broad, the remaining pool may be empty for some orders. * **Candidate products were out of stock or unpublished.** Products that are OOS, inactive, or not published to the Online Store sales channel are dropped before the offer renders. If your highlighted product is unavailable, Smart Funnel tries to substitute — but if no fallbacks are eligible either, nothing displays. * **Non-English checkout locale.** Smart Funnel only runs when the *shopper's* checkout locale is English — it reads the locale Shopify sends with the order, not your store's primary language. An English store still skips Smart Funnel for a shopper who checked out in another language, and those orders fall through to your regular funnels instead. * **0% max discount.** A max discount of 0 does not stop Smart Funnel from running — the field accepts 0–99 and the value only scales the offer's *percentage* discount. Set to 0, the product is still offered, just at full price, which usually converts poorly. Raise the max discount if Smart Funnel offers are being shown but rarely accepted. * **Order was ineligible at the Shopify level.** Confirm the order isn't tagged with a Shopify ineligibility reason (payment wallet, multi-currency, gift card, BNPL, etc.) — if it is, the post-purchase page never had a chance to load. See the ineligibility reasons in the [Order Browser Overview](/aftersell/order_browser_overview). To investigate: open the individual order in the Order Browser and check the PPU timeline for a **Products excluded** warning — it names the specific reason (e.g., Product OOS, Product Inactive, All products filtered). Then narrow the recommendation exclusion list, republish or restock the affected products, or add more fallbacks to broaden the pool. For details on how Smart Funnel selects and substitutes products, see [Smart Funnel](/aftersell/smart_funnel). *** ## I'm seeing "Out of stock / unavailable" on TYP widget Out of stock / unavailable means the Thank You Page product recommendation widget found variants for the offer product, but every variant came back unavailable for that buyer. This is usually genuine out-of-stock, but it can also be caused by region, market, or sales-channel availability restrictions. To fix it: check that the offer product is in stock and published to the sales channel your store uses. If the product is available in your Shopify admin but still showing this status, it may be restricted to a specific market or sales channel that doesn't match the buyer's context. *** ## I'm seeing "Selected variant unavailable" on TYP widget Selected variant unavailable means the specific variant configured in your offer no longer resolves from Shopify — it was likely deleted or replaced after the offer was set up. To fix it: open the offer in Aftersell, go to the product selection for that offer, re-select the product and variant you want to show, and save. This refreshes the offer's product configuration and clears the stale reference. *** ## I'm seeing "Products filtered out" on TYP widget Products filtered out on the TYP widget means the Thank You Page offer had products configured but all of them were excluded before the widget could display anything. This is distinct from No products found (where no products could be loaded at all). Products filtered out specifically means the products exist but your offer settings excluded them all. To fix it: review your TYP offer's filter settings - check for "hide if already purchased," out-of-stock exclusions, or tag-based filters that may be eliminating all available products. Add more fallback products to the offer so there's always something eligible to show. Thank You Page order detail showing Products filtered out and offer product issues *** Still stuck? Reach out via chat or email us at [support@aftersell.app](mailto:support@aftersell.app). # Order browser overview Source: https://docs.aftersell.com/aftersell/order_browser_overview The Order Browser gives you a centralized, order-level view of Aftersell performance. Use it to see which orders were eligible for a post-purchase offer, whether an offer was shown, how customers interacted with each offer slot, and where there are gaps in your setup. The Order Browser covers Post-Purchase (PPU), Thank You Page (TYP), and Rokt Thanks experiences. **Coming soon:** Checkout timeline data will be added in a future update. ## Accessing the Order Browser To access it, navigate to: **Apps → Aftersell → Order Browser** in your Shopify admin. Aftersell app navigation menu in Shopify admin with Order Browser selected You can also jump directly to a specific order's detail page from Shopify. When viewing any order in your Shopify admin, open the **More actions** menu and select **Open order browser**. This takes you straight to that order's Aftersell detail page without needing to search for it. *** ## Summary Bar At the top of the Order Browser, three metrics give you a quick pulse on performance for your selected date range. | Metric | What it means | | ---------------------- | ------------------------------------------------------------------------------ | | **Total orders** | Every order received in the selected period — eligible and ineligible combined | | **Total offers shown** | How many of those orders actually had an offer displayed | | **Upsell Revenue** | Total revenue generated from accepted offers | Order Browser summary bar showing total eligible orders, offers shown, and upsell revenue The Order Browser defaults to the Last 30 days. Use the date picker in the top-right corner to adjust the range. Data is available from **February 25, 2026 onward** — the picker will not let you select an earlier start date. Every summary metric, Total orders included, reflects only the range you have selected. Use the **Export button** (also top-right) to download the current view as a CSV. The export respects any filters you have active, so filter first if you only want a subset of orders. The CSV includes the following columns, in this order: Order, Date, Eligibility, Sales channel, Total, Currency, PPU Funnels, PPU status, PPU offer 1, PPU offer 2, PPU offer 3, TYP Funnels, TYP status, Rokt Thanks status, Payment Gateway, and Payment Wallet. There is no column picker, so every export contains all sixteen. The Rokt Thanks status column shows the same values as the on-screen badge (`Accepted`, `Shown, not accepted`, `No offer shown`, `Not loaded`). If your store does not have Rokt Thanks enabled, the column is included but the cells are empty. Order data updates every few minutes, so a very recent order may take a short while to appear. Reload the page if you are waiting on one. *** ## Performance Panels Below the summary bar, three panels break down your performance in more detail. Together they help you quickly spot eligibility issues, configuration gaps, and opportunities to improve coverage. #### Eligible Post-Purchase Orders Shows the total count of eligible orders with a donut chart breaking them down by Shown vs Not shown. A high "Not shown" proportion usually points to funnel configuration gaps, product filtering, or Shopify eligibility issues. See the Order Browser Troubleshooting guide for next steps. #### Improvement Opportunities This panel highlights eligible orders where at least one offer didn't render because of funnel, offer, or product configuration gaps. Some of these orders may have shown other offers — fixing these gaps widens overall coverage. The panel is split into two categories: Funnel & Offer opportunities and Product opportunities. For each reason, the panel shows how many eligible orders were affected. **Funnel & Offer opportunities** **What it means:** An eligible order came through but no funnel matched its trigger conditions. **What to do:** Create a catch-all funnel using the **Show for All Customers** trigger and set it to the lowest priority so it fires whenever no other funnel matches. **What it means:** A funnel ran but one or more offer slots had no offer set up. **What to do:** Go to the funnel and add an offer to the empty slot. **What it means:** A funnel matched the order but has no offers configured, so nothing could be shown. **What to do:** Open the funnel and add an offer to at least one slot. **What it means:** Your store had no active funnel available to serve this order at all. **What to do:** Create a funnel and enable it. **What it means:** A funnel was configured and matched the order, but every product across all offer slots was filtered out by your targeting or filter rules before anything could display. **What to do:** Review your funnel's product filters and targeting rules. Broaden the filter criteria or add fallback products to ensure at least one offer has something eligible to show. **What it means:** An individual offer slot ran but every product in it was filtered out before the offer could display. **What to do:** Review the offer's filter settings and add more fallback products so there is always something eligible to show. **What it means:** An offer slot exists but no product has been chosen for it. **What to do:** Open the funnel and pick a product for that slot. **What it means:** An offer slot exists but no offer template has been chosen for it. **What to do:** Open the funnel and choose a template for that slot. **What it means:** The offer uses automatic recommendations and the recommendation provider returned nothing for this order. **What to do:** Add a manually-selected fallback product to the offer so it always has something to show. **What it means:** Every recommended product for the slot was out of stock at the time of the order. **What to do:** Restock, or add fallback products that are reliably in stock. **What it means:** Every candidate product was out of stock at the locations required by the offer's per-location inventory filter. **What to do:** Restock at those locations, or relax the inventory filter on the offer. **What it means:** Every recommended product for the slot sits on your store's automatic-recommendation exclusion list. **What to do:** This list is not editable from the dashboard — contact support to have it reviewed. Opportunities are tagged based on the customer's actual journey, not the funnel's configuration. For example, if a funnel has no offer set up in slot 3 but the customer declined slot 2 and never reached slot 3, it will not be flagged. The flag only appears if the customer's journey would have reached that step. You can click on any opportunity category to filter the order table to orders affected by that specific gap. **Product opportunities** **What it means:** The replacement upsell failsafe was triggered because the shop hit its replacement-failure threshold within the past 7 days. Replacement upsells are paused shop-wide until the rolling 7-day error count drops below the threshold or you reset the failsafe. Orders attributed to this reason never attempted a replacement. **What to do:** Go to **Settings → Replacement Upsells** to see the failsafe status card and your current rolling error count. Once you've resolved the underlying issue, click **Reset failsafe** to resume. If errors have stopped, the failsafe also clears automatically once the 7-day window passes. If you're unsure of the root cause, contact support before resetting. **What it means:** No line item in the order matched the replacement target's variant ID, so the replacement was skipped. **What to do:** Review the replacement upsell configuration and confirm the target variant is present in the orders you expect it to match. **What it means:** More than one line item matched the replacement target, so Aftersell could not tell which one to replace. **What to do:** Narrow the replacement target to a variant that appears at most once per order. **What it means:** The line item the replacement would have targeted already had a discount applied, and the offer's **Allow replacement if product has discount applied** toggle is off. **What to do:** Nothing, if you meant to protect discounted lines. If you do want these orders to convert, turn that toggle on in the offer's settings. **What it means:** A recommended product is sold as a subscription only, but the customer's checkout already included a subscription, so it couldn't be added as a post-purchase upsell. **What to do:** Consider replacing subscription-only products in this offer with non-subscription alternatives, or move subscription offers to the Thank You Page where this restriction doesn't apply. **What it means:** The offer product was out of stock when the order came through. **What to do:** Restock it, or add fallback products to the offer. **What it means:** The offer product was unpublished or set to inactive in Shopify. **What to do:** Republish the product, or swap it for an active one. **What it means:** The product was out of stock at the locations required by the offer's per-location inventory filter. **What to do:** Restock at those locations, or relax the inventory filter on the offer. **What it means:** The product was removed by one of the offer's exclusion filters — by product tag, by metafield, by product, or by collection. **What to do:** Open the offer's filter settings and check whether the rule is broader than you intended. **What it means:** The candidate product was removed by your store-level collection exclusion rules — the first when an automatic recommendation was excluded, the second when the most/least expensive placeholder picked an excluded product. **What to do:** These come from **Settings → Automatic upsells**, not from the funnel. Review the excluded collections there if the pool is coming out empty. These aren't errors. They're flags that something can be fixed to improve coverage. ### Ineligible Post-Purchase Orders Shows orders that couldn't receive a post-purchase offer, broken down by the specific reason. The panel surfaces exact counts per reason so you can see where the biggest eligibility gaps are. Shopify does not tell Aftersell exactly why an order was skipped for post-purchase. The system identifies likely reasons based on Shopify's documented limitations. Because a single order can match multiple reasons, the individual reason counts do not add up to the total ineligible number. No percentages are shown for this section for that reason. You can click on any ineligibility reason to filter the order table to just those orders. **What it means:** Order value was under \$0.50 (e.g., fully discounted orders). **What to do:** Shopify restriction — no fix. Set up Thank You Page upsells to capture these orders. **What it means:** Order included duties or landed costs. **What to do:** Shopify restriction — no fix. TYP upsells are not affected. **What it means:** Order was paid entirely with a gift card. **What to do:** Shopify restriction — no fix. TYP upsells are not affected. **What it means:** Order used a BNPL method (Klarna, Afterpay, Shop Pay Installments). **What to do:** Shopify restriction — no fix. TYP upsells are not affected. **What it means:** Order used a local delivery method not supported for post-purchase. **What to do:** Shopify restriction — no fix. TYP upsells are not affected. **What it means:** Order was placed in a currency other than the store's default. **What to do:** Shopify restriction — no fix. TYP upsells support multi-currency and will show to these customers. **What it means:** Shipping address was missing a country code. **What to do:** Typically a data issue on the order. No fix available for past orders. **What it means:** Order used a non-credit-card payment method not supported by Shopify. **What to do:** Shopify restriction — no fix. TYP upsells are not affected. **What it means:** Order used a third-party payment gateway that doesn't support post-purchase. **What to do:** Check if your gateway supports Shopify's post-purchase API. See Payment Methods for the full supported gateway list. **What it means:** Order used a digital wallet (Apple Pay, Google Pay, PayPal). **What to do:** Shopify restriction — no fix. Set up Thank You Page upsells to capture wallet orders — TYP is not affected. **What it means:** Shopify bypassed post-purchase for this order. Aftersell has no visibility into why — the error code shown in the order detail is `no_activity`. **What to do:** Contact Shopify support directly. Aftersell cannot investigate or resolve this — it is entirely within Shopify's platform. **What it means:** Order came through a channel that doesn't support post-purchase (e.g., POS or a third-party marketplace). Post-purchase offers are supported on orders placed through the Online Store, a supported headless or custom sales channel, or a draft-order payment link. **What to do:** No fix available. These orders bypass Shopify's standard checkout entirely, so neither post-purchase nor Thank You Page upsells can reach them. Order Browser panels with a shown-versus-not-shown donut chart and ineligibility reason breakdown Payment wallet and Unsupported sales channel tend to be the largest contributors for most stores. For payment method restrictions, [Thank You Page upsells](/aftersell/how_can_i_set_up_and_customize_thank_you_page_upsells_in_aftersell) are the best way to recover that traffic since TYP is not subject to Shopify's post-purchase restrictions. For a full breakdown of supported and unsupported payment methods, see [Payment Methods](/aftersell/payment_methods) *** ## The Order Table Below the performance panels is a detailed, order-level table. Each row is a single order. This is where you can search, filter, and drill into exactly what happened for any order. ### Columns | Column | What it shows | | ----------------------- | ----------------------------------------------------------------------------------------------- | | **Order** | Shopify order number. Click to open the order detail view. | | **Date** | When the order was placed | | **Eligibility** | Whether the order was eligible or ineligible for a post-purchase offer | | **Sales channel** | e.g. Online Store | | **Country** | The shipping country for the order, displayed as an ISO country code (e.g. US, GB, AU) | | **Total** | Order value | | **PPU Funnel** | Which post-purchase upsell funnel was shown. Click to open the funnel editor. | | **PPU offer 1 / 2 / 3** | The interaction status for each post-purchase offer slot | | **TYP Funnel** | Which Thank You Page funnel was shown | | **TYP widget** | The widget status on the Thank You Page | | **Rokt Thanks** | The Rokt Thanks offer status for the order (only visible if your store has Rokt Thanks enabled) | PPU stands for Post-Purchase Upsell. TYP stands for Thank You Page. Each post-purchase funnel can have up to three offer slots (PPU offer 1, 2, and 3), each shown or resolved independently. ### Offer Status Definitions **PPU offer statuses** (columns PPU offer 1, 2, 3) | Status | What it means | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Accepted** | The customer accepted the offer. The item was added to their order. | | **Declined** | The customer actively declined the offer by clicking the decline button. | | **No interaction** | The offer was shown, but the customer closed the tab or navigated away without clicking Accept or Decline. The offer was seen, just not acted on. | | **Customer skipped** | The customer skipped the post-purchase page entirely, or closed their browser before the offer loaded. The offer never had a chance to display. | | **Timer expired** | The post-purchase session timer ran out before the customer interacted with the offer. | | **No funnel triggered** | No funnel's trigger conditions matched this order, so no offer was selected for this slot. | | **No active funnels** | There were no active (enabled) funnels available to serve an offer for this order. | | **Not configured** | An offer slot exists in the funnel but no offer has been set up in that slot yet. | | **All offers filtered out** | A funnel was configured and matched the order, but every product across all offer slots was filtered out by your targeting or filter rules before anything could display. | | **Offer type not supported** | The offer slot's configured offer type isn't supported for this order or context. | | **Unsupported shipping country** | The order's shipping country is not on your store's allowed post-purchase countries list. This is a store-level setting, not funnel targeting. | | **Products excluded** | The offer has products configured, but all of them are being excluded by your offer settings (e.g., hide if already purchased, out of stock, unpublished). Nothing was available to show. | | **Products unavailable** | None of the funnel's configured products were available to recommend for this order. | | **No products recommended** | The offer's recommendation strategy returned no eligible products to show. | | **Recommendations out of stock** | Every product returned by the offer's recommendation strategy was out of stock. | | **No stock at location** | Every candidate product for this offer was out of stock at the locations required by the offer's per-location inventory filter. Restock at those locations, or adjust the inventory filter on the offer strategy. | | **Technical issue** | An unexpected error prevented the offer from loading correctly (for example, a funnel or customer data lookup failed). | | **Ineligible** | Shopify skipped the post-purchase page for this order due to a platform-level eligibility rule. This is a Shopify restriction, not an Aftersell configuration issue. | | **Subscription upgrade issue** | The customer accepted the offer and the item was added to their order, but the downstream subscription upgrade at your subscription provider (Recharge, Loop, or Skio) failed. Open the order to see the specific cause and what to do to fix it. | **TYP widget statuses** (TYP widget column) The interaction outcome for the offer shown on the Thank You Page. The Post Purchase funnel and Thank You Page funnel for an order can be the **same or different.** | Status | What it means | | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Accepted** | The customer accepted the offer on the Thank You Page. | | **Declined** | The customer declined the offer. | | **No interaction** | The offer was shown but the customer didn't interact with it, and the timer (if one exists) didn't trigger. | | **Timer expired** | The offer timer expired before the customer interacted. | | **Pending conversion** | The customer accepted the offer but the conversion is still being processed. | | **No activity** | The customer did not visit the Thank You Page. | | **No products found** | No products matched the offer's placement configuration, so nothing could be shown. | | **Products filtered out** | The offer's configuration filtered out all of its products, so nothing was displayed. | | **Already in order** | The widget is in "Modify original order" mode and every configured variant is already in the customer's order. Shopify does not allow duplicate variants in an order edit, so the upsell was hidden. Switch order handling to **Create new draft order** in the widget's [order handling settings](/aftersell/thank_you_page_extensions_overview#order-handling) to re-offer products regardless of what's already in the original order. | | **Order can't be modified** | The widget is in "Modify original order" mode and this order could not be edited — for example it was archived, partially paid, past the window during which Shopify allows an order edit, or its shipping cannot accept the offered products. Switch order handling to **Create new draft order** to keep offering products on these orders. | | **Wrong page** | The offer is configured to show on a different page. | | **Already shown** | The offer had already been shown to this customer. | | **Technical issue** | A technical error occurred while loading the offer, often due to server or fetch errors outside Aftersell's control. If this happens frequently, contact support. | **Rokt Thanks statuses** (Rokt Thanks column) This column is only visible if your store has Rokt Thanks enabled. | Status | What it means | | ----------------------- | ------------------------------------------------------------------------------------------------ | | **Accepted** | The customer engaged with the Rokt Thanks offer (positive engagement recorded). | | **Shown, not accepted** | The Rokt Thanks placement loaded and was shown to the customer, but they did not engage with it. | | **No offer shown** | No Rokt Thanks offer was served for this order. | | **Not loaded** | The Rokt Thanks placement did not load for this order. | **Funnel column statuses** (PPU Funnel, TYP Funnel columns) | Status | What it means | | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **No funnel triggered** | No funnel matched this order's trigger conditions. The order was eligible but no funnel fired. | | **Funnel** | A funnel matched the order but showed no offer — either no offers were configured, every configured offer was skipped, or the order had no line items with product IDs. Open the funnel and add an offer to at least one slot. | | **All offers filtered out** | A funnel was configured and matched the order, but all products across every offer slot were filtered out by your targeting or filter rules. Review your funnel's product filters and targeting to ensure at least one offer has eligible products. | | **No active funnels** | Your store had no active funnel available to serve this order. | | **Ineligible** | Shopify skipped the post-purchase page for this order under a platform-level eligibility rule. | | **Unsupported shipping country** | The order's shipping country is not on your store's allowed post-purchase countries list — a store-level setting, not funnel targeting. | | **Technical issue** | An error prevented the funnel from being resolved for this order. | The badge in the Funnel column reads simply **Funnel**. The longer wording — *Funnel not set up* — is what the same underlying reason is called in the Improvement Opportunities panel. Statuses that are frequently confused: * **Customer skipped** = the offer never loaded (the customer left before the page could show) * **No interaction** = the offer loaded and was visible, but the customer didn't click anything * **Timer expired** = the session timed out while the offer was on screen * **Ineligible** = Shopify blocked post-purchase from running at all for this order * **No funnel triggered** = the order was eligible but no funnel matched its trigger rules * **Funnel** (Funnel column) / **Funnel not set up** (Improvement Opportunities) = a funnel matched but showed no offer * **All offers filtered out** = a funnel matched and had offers configured, but every product was filtered out by targeting or filter rules * **Subscription upgrade issue** = the offer was accepted and the item added to the order, but the subscription upgrade at your provider failed — open the order for the specific cause and fix *** ## Searching and Filtering Orders ### Search Use the search bar at the top to find a specific order by name. ### Filters Click **Add filter +** to filter the order table. Multiple filters can be combined to narrow down results. Click **Clear all** to remove active filters. | Filter | What it does | | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Post-purchase status | Filter by the overall post-purchase outcome, grouped into four buckets: **Not eligible**, **No offer shown**, **Shown, not accepted**, and **Accepted**. Use this as a quick top-level filter to find all orders where a customer accepted, declined, or never saw an offer. | | Post-purchase eligibility | Filter by whether an order was eligible or ineligible | | PPU Funnel | Filter by which post-purchase upsell funnel was shown | | Post-purchase offer 1 / 2 / 3 | Filter by the status of each offer slot | | TYP Funnel | Filter by which Thank You Page funnel was shown | | Thank You page status | Filter by the outcome on the Thank You Page | | Payment status | Filter by payment method or status | | Post-purchase shown | Filter by whether the post-purchase page was shown | | Thank You page shown | Filter by whether the Thank You Page was shown | | Funnel opportunities | Filter by orders with funnel-level improvement opportunities | | Product opportunities | Filter by orders with product-level improvement opportunities | | Offer opportunities | Filter by orders with offer-level improvement opportunities | | Ineligibility reason | Filter by the specific reason an order was ineligible | *** ## Viewing an Individual Order ### Viewing an Individual Order Click any order number to open the order detail view, or use the **More actions → Open order browser** shortcut from the order page in your Shopify admin. This is a complete record of Aftersell activity for that order. Use **View in Shopify** in the top right to open the order directly in Shopify. The detailed timeline view is only available for orders placed after the Order Browser launch. Orders placed before that date will show limited timeline data. If an order has no Aftersell activity recorded, the detail page shows an informational banner instead of a timeline. This typically means one of the following: * The order was placed very recently and new orders can take a little while to appear. * The order predates your Aftersell install, so there was no activity to record. * The order came from a channel Aftersell does not track, such as POS or subscriptions. The detail view has up to four collapsible sections in the main column: **Order Summary**, **Post Purchase**, **Thank You Page**, and **Rokt Thanks** — the last shown only when the order has Rokt Thanks activity. Order Summary is expanded by default and the rest start collapsed; click a section header (the chevron on the left) to expand or collapse it. Each section displays a status badge at a glance, for example **1 Accepted** or **No interaction**, so you can understand the outcome without expanding it. The right sidebar holds the section navigation plus separate Customer, Payment method, Order tags, and Discounts codes cards. Individual order detail view with Post Purchase and Thank You Page event timelines ### Order Summary A collapsible section in the main column, open by default. It lists every product in the order — including any accepted upsells — with quantities and pricing, then the order subtotal and total, and finally the name of any Thank You Page funnel whose offer was accepted. The right sidebar holds four separate cards: **Customer** (shipping address, email, customer tags), **Payment method**, **Order tags**, and **Discounts codes**. All of it pulls from Shopify directly and requires no additional configuration. ### Post Purchase (PPU tab) A step-by-step milestone timeline of the post-purchase experience for this order. | Milestone | What it means | | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Funnel triggered** | The funnel fired for this order. Shows the funnel name (click to edit triggers) and the trigger rule that selected it. | | **Offer shown** | An offer was displayed. Shows the products that were presented, with thumbnails. | | **Offer accepted** | The customer accepted the offer, including revenue amount. If the offer included a subscription upgrade and the upgrade failed at your subscription provider, a red banner appears beneath this milestone showing the specific cause and what to do to fix it. | | **Offer declined** | The customer declined the offer. | | **Ineligible** | Shopify blocked the post-purchase page for this order. Shows the specific Shopify eligibility reason. | | **Technical issue** | The post-purchase experience failed to load — usually a server or fetch error outside Aftersell's control. (PPU never shows a *Not loaded* status; that label belongs to Rokt Thanks.) | | **Subscription upgrade failed** | The subscription upgrade at your provider failed after the offer was accepted. This row shows the specific failure cause and remediation steps. | If products were excluded from an offer, you'll see a **Products excluded** warning beneath the milestone with the specific reason. Possible reasons include: **What caused it:** Shopify blocked the order at a platform level. **What caused it:** No funnel matched this order's trigger conditions. **What caused it:** Every product in the offer was filtered out by your settings. **What caused it:** The offer slot exists but no offer has been set up. **What caused it:** The offer product was already in the customer's original order. **What caused it:** The offer product was out of stock at the time of the order. **What caused it:** The offer product was unpublished or inactive in Shopify. **What caused it:** The offer product was out of stock at the locations required by the offer's per-location inventory filter. Restock at those locations, or adjust the filter on the offer strategy. **What caused it:** The offer product was excluded by a product-tag filter on the offer strategy. Review the filter or widen the product pool in your offer strategy. **What caused it:** The offer product was excluded by a product-metafield filter on the offer strategy. Review the filter or widen the product pool in your offer strategy. **What caused it:** The offer product was excluded by a product filter on the offer strategy. Review the filter or widen the product pool in your offer strategy. **What caused it:** The post-purchase session timer ran out before the offer had a chance to load. If you placed a test order and the PPU timeline shows no events or incomplete data, it may be because the order ID wasn't available when the earliest events fired. This resolves automatically as the order completes. ### Thank You Page (TYP tab) Shows the same milestone structure as the PPU tab, filtered to Thank You Page events. A **Technical issue** badge means there was a problem loading the TYP experience for this order. *** Something not looking right? See the [Order Browser Troubleshooting](/aftersell/order-browser-troubleshooting) guide, or reach out via chat or email us at [support@aftersell.app](mailto:support@aftersell.app). # Pages vs standalone widgets Source: https://docs.aftersell.com/aftersell/pages-vs-standalone-widgets In Checkout , there are two ways to add widgets to your Checkout: **Pages** and **Standalone widgets**. This article explains how each works, when to use them, and how to get them placed in your Shopify Checkout. ### **Which should I use?** | | **Pages** | **Standalone widgets** | | :------------------ | :--------------------------------------- | :--------------------------- | | **Best for** | Displaying multiple widgets together | Displaying a single widget | | **Triggers** | Shared across all widgets in the page | Set individually per variant | | **Block limit** | Max 5 blocks per widget type | Max 3 blocks per widget type | | **Block placement** | One app block per widget inside the page | One app block per widget | *** ## **Pages** A Page is a group of widgets that share a single group of triggers. When the trigger conditions are met, all widgets within the page are displayed together. Pages are ideal when you want to show multiple widgets to the same audience at the same time. ### Creating a Page When creating a page, you have two options: **Guided setup** or **Start from scratch**. **Guided setup** The Guided setup walks you through a recommended configuration based on a goal you choose. The setup follows four steps: **Goal, Triggers, Widgets, and Placement.** **Step 1: Goal** Choose the goal that best fits what you want to achieve. Each goal comes with a recommended set of widgets pre-configured for you. | **Goal** | **Recommended widgets** | | :----------------------------------------------------- | :-------------------------------------------------------------- | | Increase Average Order Value (AOV) and conversion rate | Upsells, Trust Badges, Testimonials | | Build customer trust and reduce abandonment | Trust Badges, Cart Controls, Text | | Promote add-ons and accessories | Checkbox Upsells, Images, Testimonials | | Encourage customers to reach free shipping threshold | Upsells (with Rewards), Text | | Custom configuration | None — start from scratch and build your own widget combination | **Important:** Your goal cannot be changed after saving. If you need a different goal, you will need to delete the page and create a new one. However, widgets can be added to or removed from a page at any time. Take a moment to choose the goal that best fits your strategy before proceeding. Once you’ve selected your goal, click **Save and next** to continue. Checkout guided setup Goal step listing recommended goals to choose from **Step 2: Triggers** Set the conditions under which your page will be shown, or choose to show the page to all customers with no conditions. For a full list of available triggers, see[ Checkout Triggers](/aftersell/checkout_triggers). **Step 3: Widgets** Review the widgets that have been recommended for your goal. You can add or remove widgets at this stage, and access advanced settings for each widget. For a full list of available widget types and their settings, see[ Checkout Widget Types](/aftersell/checkout_widget_types). Guided setup Widgets step reviewing recommended checkout widgets with a live preview **Step 4: Placement** Each widget in your page needs to be placed individually in your Shopify Checkout editor. Each widget is assigned a **BlockID** (e.g., page-upsell-001, page-upsell-002) which is used to identify it when adding the app block in Shopify. Location recommendations are provided to help you decide where to place each widget on the Checkout Page to place a widget: 1. Note the **BlockID** assigned to your widget in the Aftersell dashboard. 2. Open the **Shopify Checkout editor**. 3. Add the **Aftersell app block**. 4. From the dropdown, select the BlockID that matches your widget (e.g., page-upsell-003). **Note:** Each widget within a page **has its own BlockID and must be added as a separate app block in the Shopify Checkout editor.** A widget will not display until it has been placed. Shopify Checkout editor adding the Aftersell app block and selecting its BlockID placement *** **Start from scratch** Start from scratch follows the same process as Guided setup, but skips the Goal step. You configure your triggers, add your widgets manually, and then place them in your Shopify Checkout editor using their BlockIDs. **Editing a Page** You can edit a page at any time after creation, including adding or removing widgets and updating triggers. The only thing that cannot be changed is the goal. If you need to change the goal, delete the page and create a new one. **Duplicating a Page** To create a copy of an existing page, click the **Duplicate** icon on the page row in the dashboard. The duplicated page is created in an inactive state with the name prefixed by "(Duplicated)" and includes all the same widgets and trigger configuration as the original. You can rename and activate it when ready. *** ## **Standalone widgets** Standalone widgets are individual widgets, each with their own triggers and priority and are best suited for when you only need to display a single widget all the time or to a targeted group of customers. ### Creating a Standalone widget Click **Create widget** from the dashboard. You will be prompted to select two things: * **Widget type**: The type of widget you want to create (Upsells, Rewards, Trust Badges, Testimonials, Cart Controls, Notes, Text, or Images). For a full breakdown of each widget type and its settings, see [Checkout Widget Types](/aftersell/checkout_widget_types). * **Block**: Which block to add the widget to. There are three blocks available, and the naming follows the widget type you selected. For example: * Upsells: Default upsell, Additional upsell 1, Additional upsell 2 * Trust Badges: Default trust badge, Additional trust badge 1, Additional trust badge 2 * And so on for each widget type Each block can hold multiple variants, The block counter in the top-right of the selector shows how many of the 3 available blocks you have created (e.g., 2/3 means 2 blocks created, 1 remaining). ### Block limit A maximum of **3 blocks** can be used for Standalone widgets. Once all 3 blocks are in use, the **Add new block** option will be unavailable and no additional widgets of the same type can be created until an existing block is removed. ### Placement Each Standalone widget must be placed in your Shopify Checkout editor as its own app block. When adding an app block in Shopify, you will see BlockID options for your standalone widgets listed as: * Default placement * Additional placement 1 * Additional placement 2 The placement value is a routing key, not a position: it tells the app block which stored widget configuration to load. Where a widget actually appears in checkout is decided by where you add its app block in the Shopify Checkout editor — with one exception. **Cart controls** is not freely positionable: it renders after each cart line item wherever the cart is shown. Every other widget type can be added as a block in any location the Checkout editor offers. To place a widget: 1. Open the **Shopify Checkout editor**. 2. Add the **Aftersell app block** in your desired location. 3. From the dropdown, select the BlockID that corresponds to your widget. *** ## **Analytics** Analytics are available for both Pages and Standalone widgets. You can view performance data for any individual page or widget by clicking the **bar chart icon** next to it on the dashboard, from within the editor itself or from the Analytics tab in the side navigation # Post-purchase insights Source: https://docs.aftersell.com/aftersell/ppu_insights Understand how your post-purchase funnel performance compares to similar stores using the peer benchmarks feature in Aftersell. The post-purchase insights page gives you a benchmark view of your revenue per visit (RPV) compared to stores with a similar average order value (AOV) and, where available, a similar industry. This helps you understand how your post-purchase funnel is performing relative to your peers. This feature is available to all merchants on a post-purchase plan. *** ## Accessing post-purchase insights You reach post-purchase insights from the home page: a **Peer benchmarks (PPU)** widget appears there, and **View full report** opens the full insights page. That widget is the only entry point — the report has no sidebar item of its own, and it does not live under the sidebar's **Reports** section (that is the dashboards and Explorer area, which is a different feature). *** ## Peer benchmarks widget The peer benchmarks widget on your home page gives you a quick snapshot of how your RPV compares to similar stores over the last 30 days. The widget shows: * **Your RPV** — Your revenue per visit for post-purchase offers over the last 30 days. * **Peer comparison** — How your RPV ranks against stores that share your AOV (and industry, if available). The sub-heading describes the comparison being made, for example "Compared to stores that share your AOV and industry · Last 30 days" or "Compared to stores that share your AOV · Last 30 days". * **Percentile ranking** — Where you fall within your peer group (for example, Top 25%, Average, or Below average). If your store is new to post-purchase or does not yet have enough data, the widget displays a message explaining that your benchmarks will appear as your store earns with the app. *** ## Full post-purchase insights report The full report, reached from the home-page widget, includes additional detail across several sections. ### Performance summary The section, headed **Peer benchmarks** in the app, shows three metric cards — **Revenue per visit**, **Acceptance rate**, and **PPU revenue (30d)**. Each one gives your value, your peer group's median, and a gauge spanning the peer 25th–75th percentile band, plus a tier badge. This lets you see at a glance where you sit against similar stores on each measure. The peer group is determined by: * **AOV bucket** — Stores are grouped by average order value range (for example, \$80–100 AOV). * **Industry** — When your store's industry is available, the peer group combines AOV and industry for a more relevant comparison. If there are not enough peers in the combined cohort, the comparison falls back to AOV only. The sub-heading on the performance summary describes which comparison is being used. ### Daily RPV trend The daily RPV trend chart shows your revenue per visit for each day over the last 30 days, plotted alongside the peer group median. This helps you identify patterns, seasonal dips, or improvements in your funnel performance over time. If there is not enough daily data yet, the chart displays a message to check back after a few days of activity. ### Per-funnel breakdown The per-funnel breakdown table lists each of your active post-purchase funnels alongside their individual performance metrics, including: * **Impressions** — How many times the funnel was shown. * **Acceptance rate** — The percentage of impressions that resulted in an accepted offer. * **Health status** — One of four labels — **Strong**, **Steady**, **Needs work**, or **No revenue** — based on how your funnel's acceptance rate compares to the peer group median. You can click **Edit** on any funnel row to go directly to that funnel's trigger settings. ### Recommendations The recommendations section highlights specific funnels or settings that may help improve your performance, based on your benchmark data. *** ## How the peer group is determined Aftersell matches your store to a peer group using two dimensions: | Dimension | Description | | -------------- | ------------------------------------------------------------------- | | **AOV bucket** | Your store's average order value range (for example, \$80–100 AOV). | | **Industry** | Your store's product category or industry, when available. | When both dimensions are available, the peer group uses a combined AOV + industry cohort. If that cohort does not have enough stores to produce a reliable benchmark, the comparison falls back to AOV only. The label on the performance summary and widget always reflects which comparison is being used. *** ## Notes * Benchmark data is updated on a rolling basis and reflects the last 30 days of activity. * RPV values are shown in your store's currency, converted from USD using the current exchange rate. * Stores without post-purchase access do not see the widget or the insights page. # Product Recommendation widget Source: https://docs.aftersell.com/aftersell/product-recommendation-widget-thank-you-page Configure the Thank You Page Product Recommendation widget in Aftersell: choose products, design the offer, apply discounts, and set order handling. The Product Recommendation widget displays upsell products on the Thank You page after checkout. Use it to promote specific products, drive automatic recommendations based on cart contents, or feature a collection. This page covers every setting on the widget. For the full funnel setup and Shopify editor steps, see [How to configure thank-you page widgets](/aftersell/how_can_i_set_up_and_customize_thank_you_page_upsells_in_aftersell). Add the widget from the **Thank You Page** section of your funnel by clicking **Add Widget** and selecting **Product Recommendation**. Unlike post-purchase upsells, Thank You page product recommendations are compatible with **all payment gateways** and **multi-currency stores**. Customers re-enter their payment details to complete the upsell purchase, but Aftersell automatically applies their saved shipping information to keep the checkout experience seamless. Aftersell Thank You Page editor with the Product Recommendation widget active and a product selected ## Product selection 1. Choose your product selection method: * **Specific Products** - Manually select products to display * **Automatic Upsells** - Let Aftersell recommend products based on cart contents * **Collections** - Display products from a specific collection * **Strategy** - Fill the widget from an Aftersell [Strategies](/aftersell/strategies_overview) ruleset. This option appears only when Strategies targeting is active for your store and you have not already picked products by another method. 2. Set the **maximum number of products** to display. There is no fixed maximum, but keeping the count focused (for example, 4-10 products) keeps the offer easy to scan. 3. Enable **Hide product if purchased** so customers are not shown a product they already bought in the same order. 4. Enable **Hide out of stock variants** to filter out unavailable variants so customers only see items they can actually purchase. When browsing the **Products** tab in the product picker, you can check **Active products only** to hide Draft and Archived products. This filter is off by default and only applies to the Products tab, Collections are not affected. ### Editing specific products To choose specific products, click **Add upsell products** in the widget editor. Once you have products selected, the button label changes to **Edit upsell products**. Opening the picker when products are already selected shows your current selection pre-checked. From there you can: * **Add** new products by checking them. * **Remove** existing products by unchecking them. * **Clear** the entire selection by unchecking all products. Saving the picker reconciles the widget to whatever you leave selected: added products are included, unchecked products are removed, and re-saving an unchanged selection makes no changes. Collection, AI, and Strategy upsell rows are not affected when you edit specific products. ## Display on The **Display on** setting controls where the widget appears after a customer completes their purchase: * **On every impression** - Shows the widget on both the Thank You page and the Order Status page. * **Only on thank you page** - Shows the widget on the Thank You page only. * **Only on order status page** - Shows the widget on the Order Status page only. * **Only once on order status page** - Shows the widget on the Order Status page a single time, rather than on every visit. Product recommendation Display on dropdown, Max products field, and hide-product toggles ## Offer design The **Offer design** settings control how product recommendations are presented to customers. * Choose whether products are displayed in a **horizontal** or **vertical** layout, and adjust visual elements such as borders, button styles, and spacing to match your checkout. * Add **banner text** above the offer to introduce the recommendation, highlight an incentive, or provide context for the products shown. * Configure **compare-at price** display and the color used for sale prices. * Enable a **quantity selector**, customize the quantity label, and set **minimum or maximum quantity limits**. Compare, Discount, and Sale prices offer two color families: * **Checkout branding colors** - Accent, Decorative, Info, Subdued * **Preset colors** - Success (green), Warning (yellow), Critical (red) The compare-at price color options from both the theme and our presets. Some of these settings can also be modified through your Shopify checkout editor or by other apps that offer this functionality. Two toggles complement the Automatic Discount feature: * **Show compare at price** - Display the "Compare at" price with a strikethrough. * **Show discount** - Display the discount on the upsell. ## Discounts and order handling ### Discounts Apply a discount directly to the upsell by setting a **percentage** or **fixed amount**. The discount is applied automatically when the customer accepts the offer. Customize how the discount appears with the **discount text** and **discount price color**. Discount colors can use your checkout branding colors (Accent, Decorative, Info, Subdued) or a preset (Success, Warning, Critical). If enabled, the discount display can include the **compare-at price**, shown with a strikethrough to highlight the savings. Thank You page upsell offer for a Hat showing 43 percent off with a strikethrough compare-at price Discounts follow Shopify's standard checkout discount rules. Only one line-item discount can apply to a product at a time, and discounts only combine if marked as **combinable** in Shopify Admin. In some cases, discounts may not apply if another app modifies the checkout. We recommend testing your checkout after enabling discounts. ### Order handling Order handling controls how an accepted upsell is added to the customer's order. There are two options, each with different trade-offs. * **Modify original order** - Adds the upsell directly to the existing order. Free shipping is automatically applied. You can optionally email the customer when their order is modified. * **Create new draft order** - Keeps the original order untouched and creates a separate order for the upsell. Order handling options to either modify the original order, or to create a new draft order #### When to choose each option | Use **Modify original order** when... | Use **Create new draft order** when... | | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | | You want a single fulfillment for everything the customer bought | You want to re-offer a product the customer just purchased (for example, the same item at a post-purchase discount) | | Your upsell catalog is distinct from your best-sellers | Your top-sellers are also your primary upsell candidates | | Free shipping on the upsell is the priority | You need a separate order for fulfillment or reporting reasons | | Your upsell products are not bundle products | Your upsell products include bundle products | **"Modify original order" has limitations.** When this mode is selected, a **Limitations** banner appears in the widget editor listing the following: * **Same-variant upsells are hidden.** Shopify's order-edit API does not allow duplicate variants in an order. If the customer already has the upsell variant in their original order, the upsell is hidden from the Thank You page. If an upsell is hidden for this reason, the Order Browser flags the affected order with an "Upsell hidden due to order merging" banner. * **Bundle products cannot be added to an existing order.** Shopify's order-edit API rejects bundle products. When a selected upsell variant is a bundle, the outcome follows your **When the order can't be modified** setting: * With **Hide the offer and block late acceptances**: the bundle upsell is hidden and customers cannot buy it through this offer. * With **Hide the offer, but allow late acceptances as a new order** or **Keep showing the offer and sell it as a new order**: the bundle upsell is fulfilled as a separate draft order instead of being merged into the original order. Switch to **Create new draft order** if you want bundle products or same-variant upsells to always be available to customers. #### When the order can't be modified When **Modify original order** is selected, some orders can't be edited at the time a customer accepts the upsell. There are exactly three cases: the order has been **archived**, it is **partially paid**, or it is older than the **expiry window** you set below. The **When the order can't be modified** setting controls what happens in those cases. A **fulfilled** order is not one of them, it can still be edited, but only upsell products that don't require shipping can be merged into it (see the note further down). | Option | What it does | | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Hide the offer and block late acceptances** | The offer is hidden once the order can no longer be edited. Any acceptance that arrives after the order becomes ineligible is blocked. | | **Hide the offer, but allow late acceptances as a new order** | The offer is hidden once the order can no longer be edited. If a customer accepts just before the offer hides (a race-window accept), the upsell is fulfilled as a separate draft order instead. This is the default for new widgets. | | **Keep showing the offer and sell it as a new order** | The offer stays visible regardless of whether the order can be edited. If the order can't be modified, the accepted upsell is fulfilled as a separate draft order. | The two fallback options create a separate draft order for the upsell when the original order can't be modified. The customer receives a payment link to complete the purchase as a new order. #### Setting an expiry window You can set a time limit on how long an order remains eligible for merging. Use the **Consider the order uneditable after** field (located under the behavior selector in **Order handling**) to enter a number of minutes. Once that many minutes have passed since the order was placed, the order is treated as ineligible and the **When the order can't be modified** behavior applies. Leave the field blank or set it to **0** to never expire, the offer remains eligible for as long as the order itself is editable. This is useful when your fulfillment workflow processes orders quickly and you want to avoid attempting to merge into an order that is likely already in progress. #### Other things to know about "Modify original order" * Free shipping is automatically applied and cannot be disabled. * The original order is marked as **partially paid** until the customer completes payment for the added upsell. Once payment is captured, Shopify updates the order automatically. * If the order is already fulfilled, has no shipping line, or contains only items that don't require shipping, only upsell products that **don't require shipping** can be merged into it. Products that do require shipping are dropped from the offer on those orders. ### Free shipping You can offer **free shipping** on accepted upsell products to help increase conversion. When enabled, customers are not charged shipping for the upsell, while your existing Shopify shipping settings continue to apply to the original order. How the Free shipping toggle behaves depends on your **Order handling** setting: * **Modify original order** - Free shipping is automatically applied to the accepted upsell and the toggle can't be disabled. * **Create new draft order** - The Free shipping toggle applies to the separate draft order created for the upsell. When enabled, the draft order is created without shipping charges on the upsell line item. Leave the toggle off if you want Shopify's normal shipping rates to apply to that new order. The same behavior applies when a fallback creates a separate draft order under **Modify original order** (for example, a same-variant or bundle upsell, or an acceptance after the order becomes uneditable): the Free shipping toggle controls whether the draft order is created without shipping charges on the upsell. You can also display a **"Free Shipping" badge** on the offer and customize the badge text to highlight the benefit. # Product page upsells Source: https://docs.aftersell.com/aftersell/product_page_upsells This article outlines how to setup product page upsells. The Product Page Upsells (PDP Upsells) feature in Aftersell allows you to create compelling upsell offers directly on your product pages. This guide will walk you through how to set up and optimize this feature to boost customer engagement and increase sales. *** # Introduction to Product Page Upsells The Product Page Upsells feature enables you to display relevant, complementary, or related product offers directly on the product page of your store. This functionality helps boost conversions by encouraging customers to purchase additional items. * Customers do not need to make a purchase before seeing Product Page Upsells. These appear based on triggers you set, such as specific products or page conditions. This feature mimics the popular **"Buy It Together"** experience found in many leading ecommerce platforms by offering a seamless and effective upselling opportunity without interrupting the customer's journey. *** # Setting Up Product Page Upsells ## Step 1: Create an Upsell Offer 1. Open the Aftersell Product Page Upsells dashboard and click Create New Upsell. 2. Choose which product(s) or collection(s) will trigger the upsell. 3. Select up to five products to display as upsell offers. 4. *(Optional)* Add a discount to make your offer more enticing. When a discount is applied, a value tag is shown to customers on the upsell widget, in parentheses — for example, **(\$100 OFF)** or **(CA\$130 OFF)** for fixed-amount discounts, and **(22% OFF)** for percentage discounts. The label uses the customer's presentment currency, so it always matches the actual discount applied at checkout. The wording comes from the **Discount Text** field under **Design → Pricing**, which defaults to `{{DISCOUNT_AMOUNT}} OFF` — edit it there to change the label. 5. Save your setup when complete. Aftersell New Product Page Upsell editor Configure tab with triggers, products, and discount options ## Step 2: Add the app block to the product page To display upsells on your product pages: 1. Open the Shopify Theme Editor from your Aftersell dashboard. 2. Select **Add block**, then the **Apps** tab, then **PDP Upsell**. The block is not added for you — the link opens the product template so you can place it yourself. 3. Drag it to your preferred position on the page. 4. Save your setup when complete. Shopify Theme Editor with the Aftersell PDP Upsell app block placed showing a product page preview **Note:** You can't move app blocks between sections, but you can reorder them within the same section. ## Translating Product Page Upsells Only two sections within the Product Page Upsell widget require translation. ### 1. Header Text The "You may also like" text displayed above the upsell products can be updated. To edit this: Go to **Design → Header → Heading Text** Replace the text with your preferred language. ### 2. Add to Cart Button The "Add to cart" button text can also be translated. To edit this: Go to **Design → Button → Text** Update the button text to match your store's language. # **Individual Products vs Bundles** * **Individual Products:** Customers can add upsell items separately * **Bundles:** Customers can add multiple products at once with a single discount or a Buy X, Get Y Free offer. *** # Compatibility with Shopify Themes Product Page Upsells requires a Shopify theme that supports adding app blocks.\ Most modern themes (2021 and later) are compatible. If you're using an older "vintage" theme, please upgrade to a newer Shopify theme to enable app blocks and unlock this feature. Most modern themes (2021 and later) are compatible. If you're using an older "vintage" theme, please upgrade to a newer Shopify theme to enable app blocks and unlock this feature. *** # Discounts and strategy pricing When you configure a discount on a product page upsell widget, the discount applies to all products the widget returns. If you also assign a strategy to the widget, and that strategy includes per-rule price adjustments, the two discount sources work together on a per-product basis: * **Products targeted by a strategy rule discount** — the strategy's rule discount applies to those products. * **Products returned by the strategy but not targeted by a rule discount** — the widget's configured discount applies as a fallback. * The two sources never stack. Each product receives exactly one discount — either the strategy rule's adjustment or the widget discount, never both. When the selected strategy carries a rule discount, the widget editor shows an informational banner: > *"This strategy applies its own discount to the products it targets. The discount below is the fallback for products it doesn't discount."* The discount section remains fully editable. You can configure the widget discount as the baseline for any products the strategy returns but doesn't specifically discount. > **Note:** Strategy price adjustments apply to Product Page Upsells V2, a newer version of this feature that is not yet generally available — V1 upsells have no strategy field at all. Stores are moved to V2 by the Aftersell team, and only stores already using Strategies are eligible. *** # **Limitations** * Subscription-only products can't be used as upsells. * Bundles won't appear if an included product is out of stock, this ensures accurate pricing and protects margins. *** # Translating product page upsells Only two sections within the Product Page Upsell widget require translation. ### 1. Header Text The "You may also like" text displayed above the upsell products can be updated. To edit this: Go to **Design → Header → Heading Text** Replace the text with your preferred language. ### 2. Add to Cart Button The "Add to cart" button text can also be translated. To edit this: Go to **Design → Button → Text** Update the button text to match your store's language. *** # **Final Steps** Once you've added the app block and created your offer, activate your upsell to start increasing conversions. Aftersell Your Upsells table with the status toggle highlighted to activate the upsell *** By following these instructions, you can implement the Product Page Upsells feature to enhance your store's sales potential. For help setting up or troubleshooting, please contact the **Aftersell Support Team** directly from the app. # Product targeting API security tokens Source: https://docs.aftersell.com/aftersell/product_targeting_api_security_tokens Generate and manage security tokens to authenticate API requests for product targeting strategies Security tokens allow you to authenticate API requests when accessing your product targeting strategies programmatically. You can generate, view, and regenerate tokens directly in the Aftersell admin. ## Generating a security token To generate your first security token: 1. Navigate to **Settings → Product Strategy** in the Aftersell admin 2. Locate the **Security Token** card at the top of the page 3. Click **Generate Token** 4. Your new token will be displayed - click **Copy** to copy it to your clipboard ⚠️ **Important:** Make sure to copy your token immediately after generation. You won't be able to see it again after you leave the page. ## Viewing your token After generating a token, you can: * **Show/hide the token:** Click the eye icon to toggle visibility * **Copy the token:** Click the **Copy** button to copy it to your clipboard The token is masked by default for security. Once you navigate away from the page, the token will be permanently hidden and can only be regenerated (which invalidates the previous token). ## Regenerating a token If you need to create a new token (for example, if your current token was compromised): 1. Navigate to **Settings → Product Strategy** in the Aftersell admin 2. In the **Security Token** card, click **Regenerate** 3. Your new token will be displayed - click **Copy** to save it ⚠️ **Warning:** Regenerating a token will immediately invalidate your previous token. Any API requests using the old token will fail. Make sure to update all systems using the old token before regenerating. ## Using your security token Send your security token in the `X-Strategy-Api-Key` header on every Strategy API request. Keep your token private and secure - treat it like a password. Only one token can be active per store at a time. Generating a new token immediately invalidates the previous one, so a single token has to be shared by every environment that calls the API - you cannot issue separate development, staging, and production tokens. 💡 **Best practices:** * Store tokens securely (never commit them to version control) * Regenerate tokens if you suspect they've been compromised * Update every system that uses the token before you regenerate it, since the old token stops working immediately * Keep a record of when tokens were generated and where they're being used # Manage reports Source: https://docs.aftersell.com/aftersell/reports_dashboards Create and manage custom analytics reports in Aftersell's Reports section. The Reports section lets you build custom reports from saved queries, giving you a flexible view of your store's analytics beyond the standard Analytics tabs. *** ## Navigating your reports When you open the Reports section, you land on the **Reports** table. This table lists every report available to your store, including default reports (provided by Aftersell) and any reports you have created. Each row in the table shows: * **Name** — the report name * **Type** — either **Default** (a report provided by Aftersell) or **Custom** (a report you created) * **Last updated** — the date and time the report was last modified * **Delete** — available on your own (Custom) reports only; Default reports cannot be deleted Click any row to open that report. *** ## Creating a report To create a new report, click **Create report** in the top-right corner of the Reports table. This immediately creates a new blank report named `Untitled report N` and opens it in view mode. Click **Add widget** to start filling it. If you have no reports yet, the same **Create report** button appears in the empty state. *** ## Report controls Three controls apply to every widget on the report at once, so all cards stay in sync. By default, each control is set to **Chart Default**, which inherits the date range, comparison, and timezone of widgets added to the report. * **Date Range** — set the period you want to see. * **Comparisons** — compare the selected period against another. The options are **Chart default**, **No comparison**, and **Previous period**; year-on-year is not offered, because reporting data does not yet go back a full year. * **Time Zone** — set the timezone used for dates and time-based grouping. *** ## Renaming a report You can rename any report you created (Custom reports only — Default reports cannot be renamed). 1. Open the report by clicking its row in the Reports table. 2. Click **Edit report**. A **pencil icon** appears next to the report title in the header. 3. Click the pencil icon, type the new name, and press **Enter**, or click away to save. *** ## Editing a report To add or rearrange widgets on a report you own: 1. Open the report. 2. Click **Edit report** in the header. 3. In edit mode, a **Widgets** panel appears on the left. Drag a saved query from the panel onto the grid to add it as a widget. 4. You can also click **Add widget** to build a new query in the Explorer and add it to the report. 5. When you are done, click **Save** to keep your changes, or **Cancel** to discard them. Default reports (Type: Default) are read-only and cannot be edited. *** ## Widgets Each item on a report is a **widget** — a saved query rendered as a visualization. For adding, configuring, and arranging widgets, see [Manage widgets](/aftersell/reports_widgets). *** ## Sharing a report When viewing a report, click the **Share** button in the header to generate a shareable link. The recipient opens the report in fullscreen view. The link can only be opened by users authenticated to your Shopify store. *** **Need help?** Contact the Aftersell support team through your report. # Explorer Source: https://docs.aftersell.com/aftersell/reports_explorer Build custom analytics queries and reports using the Explorer in Aftersell. The Explorer lets you build custom analytics queries using a flexible query builder (AftersellQL). You can select metrics, group results by dimensions, apply filters, and visualize data in charts or tables. Saved queries can be added to reports as widgets for ongoing monitoring. You build queries visually with menus — no syntax required. If you prefer to type queries directly, the Explorer also exposes the underlying AftersellQL text. See [Writing AQL queries](#writing-aql-queries) below for the syntax reference. *** ## Available metrics These are the metrics you can pick in the Explorer, grouped the same way the metric picker groups them. ### Revenue & profit | Metric | Description | | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Revenue** | Upsell revenue in your store's native currency. | | **Revenue (USD)** | Upsell revenue normalized to USD for cross-currency comparisons. | | **Revenue Per Visit** | Upsell revenue per impression session. Cannot be broken down by product, placement, funnel, or device. | | **Avg. Conversion Value** | Revenue per accepted offer. Also referred to as Average Upsell Value. | | **Upsell Revenue Per Order** | Upsell revenue (USD) divided by total orders. Store-level only. | | **Product Profit** | Revenue minus cost of goods sold (COGS) for upsold products. Relies on merchant-configured COGS, so treat it as an estimate: products without a tracked cost report revenue as profit, and cost coverage varies by store. Product-grain only; cannot be broken down by funnel, placement, or device. | ### Conversions | Metric | Description | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Conversions** | The number of accepted-offer events. One accepted offer is one conversion, so a session that accepts two offers counts twice. | | **Accept Rate** | Session-based: the share of sessions that saw an offer and accepted at least one. It is computed independently of Conversions, from a different rollup, so it is not Conversions ÷ Impressions. | | **Units Sold** | Total units sold through upsell offers. | | **Decline Rate** | Percent of post-purchase offers explicitly declined. Post-purchase only. | ### Engagement | Metric | Description | | --------------- | ---------------------------------------------------- | | **Impressions** | Unique sessions that saw an offer. | | **Show Rate** | Percent of decisions that resulted in an impression. | ### Store performance | Metric | Description | | ----------------------------- | -------------------------------------------------------------------------------------------------------------------- | | **Total Store Revenue** | Total Shopify-paid order revenue. Store-level only — cannot be broken down by surface, funnel, placement, or device. | | **Orders** | Total Shopify-paid orders. Store-level only. | | **Average Total Order Value** | Store revenue divided by orders. Store-level average order value. | ### Rokt network | Metric | Description | | ------------------------------ | ---------------------------------------------------------------------------------------------------- | | **Rokt Revenue** | Rokt-network revenue attributed to your store. | | **Rokt Transactions** | Rokt-network transaction count for your store. | | **Rokt Revenue / Transaction** | Rokt revenue divided by transactions per time bucket. | | **Rokt Impressions** | Total Rokt-network impressions across your store's placements. Distinct from upsell **Impressions**. | | **Rokt Referrals** | Rokt-network referrals — positive engagements that sent the shopper to a Rokt partner. | *** ## Dimensions Dimensions let you break down metrics by a specific attribute. Not all dimensions are compatible with every metric. Some dimension and metric combinations are incompatible. For example, **Decline rate** and **Show rate** cannot be broken down by **Currency**. The Explorer automatically prevents incompatible combinations. ### Available dimensions | Dimension | Description | | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | **Date** | Groups results by day, week, or month. | | **Surface** | The upsell surface. One of PPU (post-purchase), Checkout, Thank You Page, or Cart. | | **Funnel** | The specific funnel the offer belongs to. | | **Product** | The upselled product. | | **Placement** | The placement within a funnel. | | **Device** | The device type: Mobile, Desktop, or Unknown. There is no separate tablet value. | | **Currency** | The ISO currency code (for example, USD, EUR, GBP). Useful for multi-currency stores. Compatible with store-level metrics and most upsell metrics. | ### Unavailable dimensions The following dimensions are a work in progress. They appear in the picker but are not yet available as a breakdown. Instead, they show as 'Not compatible' for every metric. **This document will be updated when these dimensions are fully implemented.** | Dimension | Description | | ----------------- | -------------------------------------------------------------- | | **Flow type** | The type of upsell flow. | | **Experiment** | The A/B test or experiment variant. | | **Outcome** | The decision outcome (for example, eligible, out of stock). | | **Reason code** | The reason for a decision outcome. | | **Scope** | The decision scope (Flow, Experience, Placement, or ItemSlot). | | **Response type** | The offer response (Accepted, Declined, or Timeout). | *** ## Writing AQL queries Every query you build in the Explorer is an **AftersellQL (AQL)** statement. Most of the time you build queries visually — picking metrics, dimensions, filters, and a date range from menus — and never need to write AQL by hand. For power users, the Explorer also exposes the underlying query as editable text. This section is the reference for that text form: what the clauses mean, what values they accept, and a few ready-to-use examples. ### How an AQL statement reads An AQL statement is a single question made of clauses. Only `SELECT` and a time range (`SINCE`) are required; everything else is optional. When you include optional clauses, they must appear in the order shown below. ```text theme={"theme":{"light":"snazzy-light","dark":"github-dark"}} SELECT -- what to measure (required) WHERE -- narrow the data GROUP BY -- break the numbers down SINCE