2.0 Beta

Smootify 2.0 is in public beta. Your 1.x store keeps working. Move when you want.

What changed

Run your scripts with Smootify

How your own code waits for Smootify, with window.Smootify.push, script type smootify-load or the smootify:loaded event, and the order in which they run at load.

v2.0 beta
Open .md1.x page ↗
On this page
  1. Let Claude write it, in Smootify Studio
  2. Where to put your code
  3. 1. window.Smootify.push (recommended)
  4. 2. <script type="smootify-load">
  5. 3. The smootify:loaded event
  6. The order at load
  7. Types
  8. Where people get stuck
  9. Coming from 1.x

Smootify loads as an asynchronous module. A plain script on the page usually runs before it: window.Smootify is not ready yet and the first events have already been missed. This page shows the three ways to make your code wait for Smootify, and the order in which they run.

Let Claude write it, in Smootify Studio

Smootify Studio, the desktop app for Mac and Windows, gives each site its own folder of custom scripts, and writes them with you through Claude:

  1. Write with Claude. A conversation opens in the app, in the script’s folder, with Smootify’s custom-script skill and the site’s details already loaded. Claude asks what the script should do, then writes it with Smootify’s conventions: window.Smootify.push, the events and their payloads, the markup of the page, and the types below.
  2. Try it on the site. Studio’s dev server runs your latest code on the real site at every reload, with no publishing to see a change.
  3. Build. One click type-checks the source and turns it into the single file the site loads.
  4. Put it on the site. Claude tells you how. A small script goes inline, pasted in the site’s custom code. One too big for Webflow’s custom code limits is uploaded to your own Cloudflare R2 storage, and the site loads it from there.

You can open the folder in your own editor or terminal at any time. Claude runs on your own Claude account.

Where to put your code

  • Every page: Site settings, Custom code, in the Head code or the Footer code.
  • One page: the page settings, Custom code.
  • One place in the layout: a Code Embed element.

window.Smootify.push works from all of these places, and from a tag manager.

<script>
  window.Smootify = window.Smootify || [];
  window.Smootify.push((Smootify) => {
    Smootify.on("cart_updated", (cart) => console.log(cart.totalQuantity));
  });
</script>

This is the same pattern as window.Webflow.push. Before Smootify loads, window.Smootify is a plain list of functions. When Smootify starts, it runs them with the API as the argument.

  • When it runs. As soon as Smootify knows the visitor and the market, before it loads products and the cart. The session, the market and the price format are known at that point.
  • Listeners and filters. A listener added there gets the events from the first product_loaded and cart_updated on. A filter added there applies from the first request to Shopify.
  • Functions pushed later. A function pushed after Smootify has loaded, by a tag manager for example, runs right away. By then the first events may have gone out: { replay: true } on Smootify.on also calls your handler with the last one.
  • Errors. A function that throws is logged in the console and does not stop the others.

For data, use the async methods, such as getCart() and getCustomer(). To run code once everything has loaded, wherever the script sits:

window.Smootify = window.Smootify || [];
window.Smootify.push((Smootify) => {
  Smootify.on(
    "loaded",
    () => {
      // the session, the market and the cart are known
    },
    { replay: true },
  );
});

2. <script type="smootify-load">

Use it for code that must not run before Smootify but does not call its API. The typical case is a snippet from a third-party app that calls Shopify’s AJAX API (/cart.js) or wraps fetch. Paste the snippet as it is and change only its type:

<script type="smootify-load">
  fetch("/cart.js")
    .then((response) => response.json())
    .then((cart) => console.log(cart.item_count));
</script>

The browser does not run a script with this type. Smootify runs it right after smootify:loaded, as a normal script. To give it another type, such as a module, add data-type="module". Its other attributes are kept.

What these snippets can call is in Shopify AJAX API.

3. The smootify:loaded event

This is the 1.x way. It works only when the listener is registered before Smootify finishes loading, for example in the Head code:

<script>
  document.addEventListener("smootify:loaded", () => {
    window.Smootify.getCart().then((cart) => console.log(cart.totalQuantity));
  });
</script>

The event fires once per page. Code added later, by a tag manager for example, never sees it. In 2.0, use push.

The order at load

What happens when Smootify loads, and where each way of waiting runs:

event goes out1your code runs, by its way of waiting above
1Reads window.SmootifyUserOptionsSet it before the loader script: see Options.nothing yet
2Finds the visitor's market and sessionuser_auth_changeThe first one goes out before your functions run.
3Runs the push functions1window.Smootify.pushThe listeners and filters they add get every step below.
4Loads the cartcart_updated
5Has loadedsmootify:loaded3smootify:loaded listeners2smootify-load scriptsThe listeners first, then the scripts.
6Announces each product on the pageproduct_loadedOnce per product.

Because of step 2, a push function that needs the session uses getCustomer(), or listens to user_auth_change with { replay: true }. More in Events.

Types

smootify.d.ts describes window.Smootify, the events with their payloads and the filters. Each release publishes it at https://cdn.smootify.io/assets/v2/<version>/smootify.d.ts.

  • In a TypeScript project, add the file to include in tsconfig.json.
  • In a plain script, in an editor such as VS Code, start the file with // @ts-check and /// <reference path="./smootify.d.ts" />.

With either setup, window.Smootify and document.addEventListener("smootify:…") get their types. The methods, the events and the filters are the API. The Smootify elements on the page are not: do not script against their internals.

Where people get stuck

Check these first

  • window.Smootify is undefined, or has no methods. The script ran before Smootify loaded. Put the code in a push function.
  • A tag manager script never sees smootify:loaded. The event fires once per page, before the tag manager adds the script. Use push with Smootify.on("loaded", fn, { replay: true }).
  • The options have no effect. SmootifyUserOptions is set after the loader script, or a second script replaces the first one. Set it once, before the loader.
  • A third-party snippet gets a 404 for /cart.js. It ran before Smootify, so Webflow answered. Change its type to smootify-load.
  • A listener misses the first user_auth_change. It goes out before the push functions run. Add { replay: true }, or call getCustomer().

Coming from 1.x

smootify:loaded and <script type="smootify-load"> work as in 1.x. window.Smootify.push is new in 2.0: use it for scripts that can run late, such as the ones a tag manager adds. The window.* hooks of 1.x are replaced by filters.

    ↑ ↓ to moveEnter to openEsc to close