# 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.

Status: Ready (Smootify 2.0)  
1.x page: https://docs.smootify.io/docs/custom-code/js  
URL: https://www.smootify.io/docs/developers/scripts  
Updated: 2026-10-01

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](https://www.smootify.io/desktop-app), 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.

## 1. `window.Smootify.push` (recommended)

```html
<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](https://www.smootify.io/docs/developers/filters) 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:

```js
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:

```html
<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](https://www.smootify.io/docs/developers/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:

```html
<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:

1. Smootify reads `window.SmootifyUserOptions`. Set it before the loader script: see [Options](https://www.smootify.io/docs/developers/options).
2. It finds the visitor's market and session. The first `user_auth_change` goes out here, before your functions run.
3. The `push` functions run (way 1). The listeners and filters they add get every step below.
4. The cart loads and `cart_updated` goes out.
5. `smootify:loaded` fires and its listeners run (way 3), then the `smootify-load` scripts run (way 2).
6. Each product on the page is announced once with `product_loaded`.

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](https://www.smootify.io/docs/developers/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

> [!STUCK]
> - **`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](https://www.smootify.io/docs/developers/filters).
