# Custom themes

> How to run AndOr widgets on a theme that is not Dawn or Horizon, including Ajax redraws, cart events and the reload fallback.

Source: https://backtrackhq.com/docs/developers/custom-themes/

This page is for themes other than Dawn and Horizon. Those two get some
extra cart handling. On other themes, a few small steps keep the widgets
in sync with your theme's own cart and Ajax code.

## Placing widgets

- **App blocks** go in any section that accepts app blocks, on the
  templates each block allows. See
  [App embed and blocks](https://backtrackhq.com/docs/developers/app-embed-and-blocks/).
- **One-line tags** go anywhere your theme code renders. Use them where a
  section takes no app blocks. See
  [One-line tags](https://backtrackhq.com/docs/developers/one-line-tags/).
- **Product card recipes** go in your card snippet. If your theme names
  the card's product something other than `card_product` or `product`,
  edit the recipe's `andor_item` line. See
  [Product card recipes](https://backtrackhq.com/docs/developers/product-card-recipes/).

## After an Ajax or Section Rendering swap

The widgets keep no references to elements, so new markup is handled by
calling `refresh()` again. After your theme replaces product markup with
Ajax or the Section Rendering API, call:

- `window.AndOrDisplay.refresh()` to re-price sale price hosts.
- `window.AndOrWidgets.refresh()` to re-run badge, countdown and offers
  sale windows.
- `window.AndOrEvents.refresh()` to fire mount and change events now.

Each one exists only on pages that load its file, so check for it before
you call it. See [JavaScript API](https://backtrackhq.com/docs/developers/javascript-api/).

## Cart events the widgets listen to

Send Shopify's standard theme events and the widgets redraw by
themselves: `shopify:cart:lines-update`, `shopify:cart:view`,
`shopify:section:load` and `shopify:product:select`. See
[Events](https://backtrackhq.com/docs/developers/events/#events-the-widgets-listen-for) for
what each one triggers.

The loader also counts these as signs of a cart, and loads the cart
scripts when it sees one:

- A submit of a form posting to `/cart/add`.
- A fetch or XHR to `/cart/add`, `/cart/change`, `/cart/update` or
  `/cart/clear`. AndOr only watches for these. It wraps nothing.

## Cart drawer

Apps cannot place a block inside a cart drawer. AndOr fills the drawer
when the theme says it opened: it listens on `document` for Shopify's
standard `shopify:cart:view` event with `context` set to `"dialog"`.
Horizon 4.0+ and Dawn 15.5+ send it. Older themes and many custom
themes do not.

To get the goal bar copy (**Also show in the cart drawer**, or
`data-drawer` on the tag) and the drawer claim rows on your theme:

- Dispatch `shopify:cart:view` when your drawer opens, with
  `context: "dialog"` on the event.
- Dispatch it from the drawer's cart items element, and let it bubble.
  The bar is copied to the top of the element that sent the event.
- Send `shopify:cart:lines-update` after each cart change, so the copy
  stays in step with the cart.

Shopify documents both events in
[Standard storefront events](https://shopify.dev/docs/api/storefront-events-and-actions/events).
Horizon 4.0+ and Dawn 15.5+ load Shopify's library that sends them.

If your theme sends neither event, the drawer shows no AndOr widgets.
The page's own widgets still work, and update on the next page load
instead of the moment the cart changes.

## Upsell adds and the reload fallback

- If your theme has `Shopify.actions.updateCart`, upsell adds use it,
  then call `Shopify.actions.openCart()` so your theme opens its cart.
- If it does not, or the shopper is on `/cart`, the item is posted to
  `/cart/add.js` and the page reloads.
- After a gift removal outside Dawn and Horizon drawers, the page
  reloads.

If your cart does not redraw after a gift add or removal, the merchant
can turn on **Reload the page after a gift is added or removed** in the
offer's gift settings. See [Cart updates](https://backtrackhq.com/docs/developers/cart-updates/).

## Debugging

- Turn on **Log AndOr display decisions to the browser console** in the
  app embed while you test. Turn it off after.
- Check [Widgets not showing](https://backtrackhq.com/docs/help/widgets-not-showing/) for the
  common reasons a widget stays empty.
