window.next
Available after the sdk.ready event (next.on('sdk.ready', fn), or its alias ready; a listener added later gets it too).
A script that may run before the SDK, in <head> or from a tag manager, queues a callback in window.nextReady. It is called with window.next once the page is ready, or at once when the page already is. It works before or after the loader's <script>:
(window.nextReady ||= []).push((next) => {
next.on('order.paid', (order) => …);
});A callback that throws is logged (nextReady callback failed); the others still run.
| Member | Does |
|---|---|
next.version | SDK version |
next.on(event, fn) | Listen to an event, starting with the ones this page already sent; returns an unsubscribe function |
next.analytics.on(name, fn) | Listen to a tracking event by name, or '*' for every one (Analytics, Destinations) |
next.snapshot() | What the page shows now: campaign, cart, checkout, order, selectors, the same objects the events carry |
next.getState() | The SDK's internal state, for debugging; its shape changes between releases |
next.context() | The page, campaign, session, attribution and browser now, as on tracking events |
next.bind(root) | Bind attributes inside markup added after the page loaded |
next.log.level | What reaches the console: debug, info, warn (default), error, silent; ?debug=1 starts at debug |
next.log.entries() | The last 200 SDK log entries { level, message, data?, at }, whatever the level |
next.log.stream(fn, { replay? }) | Call fn with every new entry (and the earlier ones with replay); returns an unsubscribe function |
next.query(path) | A value of the object model, as data-next-query reads it: await next.query('cart.total'). A promise: its code loads on the first call, so a page that never asks never downloads it. next.snapshot() has the same objects at once |
next.watch(path, fn) | Calls fn with the value once its code has loaded, then each time it changes; returns an unsubscribe function |
next.define(type, name, fn, { format? }) | A field the page computes on every object of a type (Cart, CartItem, Selector, Option, Order, OrderItem), read like the SDK's own; never sent with events |
next.actions.<name>({ … }) | Every action data-next-action names, with one object of the model's field names; resolves to { ok, errors? } and never throws. See Actions |
next.actions.setGroup(id, { lines, vouchers? } | null) | Replace (or remove) a named group of lines |
Kept for 0.4.x page scripts, each marked @deprecated with its replacement: addItem({ packageId, quantity }), clearCart(), swapCart(items), applyCoupon(code), getPackage(id), getCampaignData(), getCartData() (0.4.x shape), exitIntent(options) (its id and name options name the popup on its promotion.* events), getShippingMethods(), setShippingMethod(id), getSelectedShippingMethod(), and the next:ready / next:initialized window events.
The other 0.4.x members are gone; no live page calls them. parity-0.4.md lists each one with what to use instead.
Actions
| Action | Takes |
|---|---|
addItem | items ("1x2, 5"), or package_id and quantity, or selector_id for its picked option; replace empties the cart first |
removeItem | package_id |
setQuantity | quantity ("+1", "-1" or a number) and package_id or selector_id; min_quantity, max_quantity |
select | selector_id, option_id |
clear | — |
applyCoupon / removeCoupon | code |
setShipping | shipping_id |
acceptUpsell / skipUpsell | selector_id or items: what the offer adds to the order, on a page opened with ?ref_id |
go | url: opens it with the visit's parameters |
await next.actions.addItem({ package_id: 42, quantity: 2 }); // { ok: true }
await next.actions.applyCoupon({ code: 'nope' }); // { ok: false, errors: { code: 'code "NOPE" was not applied' } }The 0.5 calls addItem(packageId, qty), removeItem(packageId), setQuantity(packageId, qty), applyCoupon(code), removeCoupon(code) and setShipping(id) still work, with their old results.
Debugging with ?debug=1
?debug=1 on the page URL sends every SDK log line to the console and adds a round N button in the bottom-right corner. Debug mode then stays on for every page of the browser tab, so it follows the shopper through the funnel, and the panel opens on each page as it was left. ?debug=0 or Turn off debug in the menu ends it. The button shows the number of issues on the page; click it for a menu with the campaign, SDK version, cart, the country, currency and language in use, a link into each panel tab and the Developer mode switch. The gear in the menu opens the settings: Page config, Theme (the system's light or dark, or one picked for the rest of the tab) and Position (the left or right side; the dock icon in the panel does the same). The panel is drawn with tsugi.
Page config shows the page's whole window.nextConfig by part (Analytics, Language, Checkout, Page), marking a value set by a 0.4.x key, tried on the tab or edited, and, on its Code tab, the block written in the current keys; Copy and Download .js (next-config.js) take it for the page. Its switches and fields edit that block; Try on this tab runs every page of the browser tab with it while debug mode is on, and the menu says so until Reset. apiKey and funnel are read before the SDK starts: they are shown, never tried, and left out of the block (put them on the script tag).
The panel starts simple: Journey, Issues, Checkout, Analytics and Events, without the codes a developer reads. Over it float three switches for the country, currency and language in use, each marked when it differs from the visitor's geo (hover for how); the globe in its header opens the visitor's geo. Developer mode adds a Developer tab, named after the tool open, whose dropdown holds Elements, State, Logs, Performance, Pick an element and the API, funnel and storage scope, and the detail inside the other tabs: package ids and SKUs, the selector a cart line came from, when the cart was priced, Raw state, the totals formula, and the storage scope of each page. The choice stays for the rest of the browser tab.
| Tab | Shows |
|---|---|
| Journey | The whole visit of this tab, drawn as tsugi's journey. A line on top sums it up: what the cart or order holds now, what upsells brought in, how many pages, and the Issues tab's count, which opens it. Below, one step per page, joined by a line: Entry first (an ad click, a campaign link, a referral or a direct visit, its ad platforms, and a warning when its parameters were not captured, kept or carried), then each page with its kind (Landing, Checkout, Upsell, Receipt), how long it was open and badges for what it added to the order (the order at checkout, an accepted upsell's amount), an upsell's outcome, the page open now, reloads and issues, then its title, path and the cart or order it held. The top line adds what upsells brought in. Click the entry for its parameters; click a page for what happened there, one line each with issues marked, whether the cart or order carried over, and its tracking events. Clear keeps only this page |
| Issues | Everything on this page that needs a look, in one list the button counts: problems the other tabs found (a cart that did not carry over, a refused coupon, card fields missing from the checkout, an order the server refused, a tracking event missing a field its dl_* push needs), elements whose data-next-* setup does not resolve (unknown path, unreadable condition, a package missing from the campaign), then logged warnings and errors. Click a problem to open where it is: this page's Journey detail with the line marked, the Checkout step it is about, highlighted, or the Analytics event that has it. Earlier pages' problems are counted once, with a link to Journey, and setup notes (GTM dataLayer on without a GTM container) are listed without being counted |
| Checkout | On every page, the cart as campaign-client draws it: each line with its variant, a quantity stepper, the price before and after discounts and per unit, a badge when it came from a bundle selector or a toggle; open a line for its package id, SKU, each discount and selects to switch it to another variant (Size, Color). Add or change packages lists every package of the campaign with its price, filtered to the purchasable ones (or recurring, or those in the cart) and searched by name, SKU or #ref_id; Add and the stepper change the cart at once, ↑ ↓ and Enter add from the keyboard. Vouchers and shipping sit beside the totals, and under the total a line checks the server's math (89.00 − 10.00 + 0.00 = 79.00 ✓). On a page with form[data-next-checkout], above the cart: one line that says whether the order can go through ("Ready", "Not ready yet: details", "Blocked: payment"), then each step: cart, details, shipping, the payment method the checkout holds with its logo (for a card, whether its details are entered yet), the order's status or why it was refused (and the address rules service, when it is down). Below the cart, the customer: email, phone, marketing, whether the open cart is saved (the dashboard's Open Carts, for abandoned-cart emails), and the shipping and billing address written as the country writes one, from i18n-rules' address format ("Austin, Texas 78701"), with each field's error under it. Check form runs the checks a submit runs; Fill test details types a test US address and contact through the checkout, as a shopper would. Card numbers are never shown or filled |
| State | next.getState() as a tree, cart open; open branches stay open as the state changes |
| Elements | Every element with a data-next-* attribute and what it resolves to now: a display's text, the value behind a show / hide and whether it shows, a package's name and price |
| Analytics | Every tracking event this page sent, newest first, tagged by what it is about (page, product, cart, checkout, order, …), with what it carried (#1001 · Earbuds ×2 · $106.11) and ⚠ when something is off (a field its dl_* push needs, a push that did not reach the GTM dataLayer). Click one for where it went (GTM, GA4, Meta, RudderStack: received, off, or missing its tag), the items and total, and what next.analytics.on and each platform got. The filter matches the name or that line |
| Locale | The three switches over the panel: Country, Currency and Language in use, each marked when it differs from the visitor's geo, with how it compares and where the value comes from on hover. Currency and language reload the page with ?currency= and ?lang= (URL parameters); the country sets the checkout's, at once on a checkout page or on the next one. The globe in the panel header opens the visitor's geo: country, city and local time, then region, postcode, time zone, coordinates with a map link, the geo's currency, browser language, IP and source. Geo is asked once the menu or the panel opens and kept for the rest of the tab |
| Events | Every public event of this page as next.on('*') gets it, newest first, tagged by object (cart, selector, checkout, …), with what it carried in one line (cart.added Earbuds 0→1). Click one for what it carries, each in its own part: what went wrong or stopped it, what a cart change moved, the items with totals that add up (subtotal, discount, shipping, tax, total), a selector's options, the customer and addresses, then the other fields and the whole envelope. Group by action groups the events one action set off, a second or less apart, each in order with how long after the first; it stays on for the tab. The SDK's internal events are left out, and the filter matches the name or that line. Events, Analytics and Logs share one layout: each line is the time, a coloured tag (the same tag has the same colour in all three), the name, a one-line detail and the outcome on the right; chips above pick tags; click a line for its detail, with Show payload and Copy JSON. |
| Logs | Every log line of this page, newest first, tagged by where it comes from (api, analytics, GA4, Meta, RudderStack, sdk): an API call shows its method and path with the status and time, a tracking decision its event, sent or not sent, and why. Warnings and errors are marked on the left, and a chip picks them. Click a line for the full message and its data. Events are not logged; they are in Events |
| Performance | This page load, from the browser's own timings: when sdk.ready came and the page was shown (data-next-ready, marked next:ready), how long the campaign call took and how much SDK JavaScript loaded; a waterfall from navigation start of the HTML, each SDK file and each API call with those milestones, DOMContentLoaded and window load; the API calls slowest first with status and time; and LCP, CLS and INP against Google's thresholds. One load in one browser: compare before and after a change |
Hovering an element card outlines it on the page; clicking scrolls to it. Pick an element (in the menu, or in the Developer tab's dropdown), then a click on the page, shows that element and its SDK parents; the click does not reach the page, and Esc cancels. The filter narrows elements, analytics and logs, each tab keeping its own, and each tab opens at the top. Reset saved data asks for a second click, then clears this funnel's saved cart, form and order.
From the console, nextDebug.explain(el) gives the same for one element; with an element selected in DevTools, nextDebug.explain($0).