Recording cart refresh
Most Shopify merchants use Giftie's configured defaults and do not need to choose a strategy here. These details are for developers adapting Giftie to a custom cart drawer, framework store, or unusual theme lifecycle.
This page covers the video/audio recording add-on managed by the standard recording controller. It does not describe greeting-card sessions or their cart flow.
Cart refresh belongs to the Giftie Shopify integration or to your custom host
code. It is not performed by window.Giftie itself.
Released default path
After a recording line is added successfully on a non-cart surface, the standard video-message controller currently:
- dispatches any outbound cart-update DOM event names supplied by the integration;
- calls
window.giftieRefreshCartUI()when that function exists and stops the fallback path if it resolves; otherwise - fetches
/cart?view=drawerand/cart.js, replaces the common cart item and totals elements, and updates common cart-count elements; and - reloads the page if that DOM refresh fails.
Under defaults, giftieRefreshCartUI is therefore auto-detected only on
non-cart surfaces. On a cart page, the released controller reloads before it
reaches that default callback path unless an enabled advanced custom-function
strategy points to a function that exists on window.
These selectors and theme APIs are best-effort implementation behavior, not a guarantee that every Shopify theme updates without configuration. Test the actual product page, cart drawer, and cart page.
Manual strategies
When Use Defaults is disabled in Giftie admin, the released Shopify theme integration runs only the enabled advanced strategies. This configuration belongs to the Shopify app and is not an SDK constructor option.
Notification strategies run before the DOM strategy:
- Pub/sub calls the theme's global
publish()function. - Custom events dispatch configured
CustomEventnames ondocumentwith{ source, cartData }indetail. - Custom function calls a named function on
windowwith the cart-add response. Errors are logged and do not stop the configured DOM phase.
Then the selected DOM behavior runs:
- Page reload reloads immediately and takes priority.
- Section rendering, auto calls a configured cart drawer's
renderContents()with inline sections when available, otherwise fetches section HTML, then falls back to the legacy DOM refresh. - Section rendering, legacy fetches the drawer view and cart JSON and replaces the common selectors.
- With both page reload and section rendering disabled, the configured path performs notifications only.
In the current release, the open drawer option is applied in the explicit
legacy path and the auto path's legacy fallback. It is not applied after a
successful direct renderContents() call. If your theme requires the drawer to
open after that path, do it in a custom bridge after rendering has completed.
Framework store or EventBus bridge
Framework storefronts should put their own state/event APIs behind a small adapter. The custom function should await fresh cart state and its application before it opens the drawer:
// Implement these methods with your framework store or EventBus.
// replace() must resolve after consumers have applied the new cart state.
const storefrontCartBridge = {
async replace(cart) {
await cartStore.replace(cart)
},
async openDrawer() {
await cartDrawerController.open()
},
}
window.giftieRefreshCartUI = async function giftieRefreshCartUI() {
try {
const response = await fetch('/cart.js', {
headers: { Accept: 'application/json' },
credentials: 'same-origin',
})
if (!response.ok) {
throw new Error(`Cart refresh failed (${response.status})`)
}
const cart = await response.json()
await storefrontCartBridge.replace(cart)
await storefrontCartBridge.openDrawer()
} catch (error) {
console.error('Unable to refresh the cart', error)
window.location.reload()
}
}
cartStore and cartDrawerController are placeholders for APIs your
storefront owns. An EventBus adapter should resolve replace() only after its
listener acknowledges that the cart state has been applied and rendered; a
fire-and-forget event can otherwise open the drawer with stale contents.
On non-cart surfaces with defaults enabled, the controller detects this function automatically. To use it on a cart page, disable Use Defaults and enable the advanced Custom function strategy with this function name. If the bridge should be the only UI updater, also disable Page reload and Section rendering; otherwise the configured DOM phase still runs after the custom function.
With a notification-only configuration, Giftie logs a custom-function failure but has no enabled DOM fallback. The bridge must own recovery itself, such as the reload in this example or an application-controlled retry/error state.
Shopify-theme renderContents() bridge
For Shopify themes whose drawer exposes renderContents(), define the function
before Giftie adds to cart:
window.giftieRefreshCartUI = async function giftieRefreshCartUI(cartAddResponse) {
const drawer = document.querySelector('cart-drawer')
if (!drawer || typeof drawer.renderContents !== 'function') {
window.location.reload()
return
}
if (cartAddResponse?.sections) {
await drawer.renderContents(cartAddResponse)
return
}
const requestedSections =
typeof drawer.getSectionsToRender === 'function'
? drawer.getSectionsToRender()
: drawer.sectionsToRender
const sectionIds = Array.isArray(requestedSections)
? requestedSections.map(section => section.sectionID || section.id).filter(Boolean)
: []
if (sectionIds.length === 0) {
window.location.reload()
return
}
const sections = await fetch(
`${window.location.pathname}?sections=${sectionIds.join(',')}`,
).then(response => {
if (!response.ok) throw new Error(`Section refresh failed (${response.status})`)
return response.json()
})
await drawer.renderContents({ sections })
}
The argument is optional in either bridge. The default compatibility path calls
giftieRefreshCartUI() without arguments; the advanced configured path passes
the cart-add response and can continue to its configured DOM strategy
afterward.
Make the function resolve only after the visible cart is consistent. await
works with both synchronous and promise-returning renderContents() methods,
but it can only wait for completion that the theme method represents. If the
method returns before its render is committed, add a theme-specific rendered
signal before resolving.
Throwing in the default non-cart path activates Giftie's legacy fallback. In the configured path, a custom-function failure is logged and the enabled DOM phase continues; when no DOM strategy is enabled, there is no Giftie fallback.
