{"title":"Liquid theme components","slug":"theme-components","url":"https://support.storeconnect.com/articles/theme-components","url_markdown":"https://support.storeconnect.com/articles/theme-components.md","subtitle":null,"summary":"Components are reusable Liquid templates that can reload themselves from the server without a full page refresh. Use them to keep parts of a page (such as the cart, order summary, or shipping rates) in sync as the shopper interacts with your store.","type":"Developer_Documentation","video_url":"","keywords":"components, theme components, component tag, liquid components, reload, defer, lazy, dynamic content, cart, order summary, storefront customization, theme development","last_modified":"2026-08-25T07:10:22+0000","body_markdown":"Components are reusable Liquid templates, much like [snippets](theme-templates), but with one important difference: a component can reload itself from the server without a full page refresh. This lets you keep part of a page up to date as the shopper interacts with your store. For example, it can refresh the cart total after an item is added, or update the order summary when a voucher is applied.\n\nThis article is for theme developers. It assumes you are comfortable creating theme templates and writing Liquid.\n\n## Overview\n\nA component has two parts:\n\n- The **component template** — the Liquid that produces the component's markup. You create it as a theme template with a key that starts with `components/`, in the same way you create a snippet.\n- The **`component` tag** — the tag you place in another template to render the component: `{% component \"name\" %}`.\n\nWhen the page first loads, the component renders inline just like a snippet. StoreConnect also wraps its output in a small container that holds an encrypted token describing the component. When a matching browser event fires, the client requests a fresh copy of the component from the server and swaps it into the page in place, with no full reload and no custom JavaScript required.\n\n## Creating a component template\n\nCreate a new theme template and give it a **Key** that starts with `components/`. The rest of the key can be anything you like, as long as it is unique for the theme. For example, to create a component named `cart`, use the key:\n\n```\ncomponents/cart\n```\n\nThe **Content** is the Liquid that renders the component. Here is a minimal example:\n\n\n```liquid\n\n{%- if current_cart != blank and current_cart.items.size \u003e 0 %}\n  {%- render \"shared/cart/items\", source: current_cart %}\n  {%- render \"shared/order_total\", source: current_cart %}\n{%- else %}\n  \u003cp\u003e{{ \"cart.empty_msg\" | t }}\u003c/p\u003e\n{%- endif %}\n```\n\n\nYou can nest components in folders by including slashes in the key, for example `components/checkout/vouchers` or `components/orders/order_summary`.\n\n## Rendering a component\n\nUse the `component` tag in any template to render the component:\n\n\n```liquid\n\n{% component \"cart\" %}\n```\n\n\nYou can pass parameters to the component the same way you pass them to a snippet:\n\n\n```liquid\n\n{% component \"orders/order_summary\", source: current_cart %}\n```\n\n\nInside the component, read a parameter with `default`:\n\n\n```liquid\n\n{% liquid\n  default source: nil\n%}\n```\n\n\nSee the [Component tag reference](component-tag-reference) for the full tag syntax.\n\n## Reloading a component on an event\n\nAdd the `reload` option to tell a component which browser events should trigger it to refresh. `reload` takes a space-separated list of event names:\n\n\n```liquid\n\n{% component \"cart\", reload: \"sc.cart-updated\" %}\n```\n\n\nWhen an event named `sc.cart-updated` fires anywhere on the page, the component fetches a fresh copy from the server and replaces itself in place. You can list more than one event:\n\n\n```liquid\n\n{% component \"cart-menu\", reload: \"sc.cart-updated sc.voucher-applied sc.voucher-removed\" %}\n```\n\n\nStoreConnect's built-in interactions dispatch events you can listen for, including:\n\n| Event | Fires when |\n|-------|------------|\n| `sc.cart-updated` | An item is added to, removed from, or changed in the cart |\n| `sc.voucher-applied` | A voucher is applied |\n| `sc.voucher-removed` | A voucher is removed |\n\nFor example, the built-in cart form dispatches `sc.cart-updated` on a successful update via `data-success=\"sc.cart-updated\"`. Any component listening for that event then reloads automatically. You can also dispatch your own custom events from your theme's JavaScript. Any component whose `reload` list includes that event name will refresh.\n\n## Loading a component later\n\nTwo options let a component load after the initial page render instead of during it. This keeps the first render fast when a component is slow to build or is not immediately visible.\n\n- **`defer`** — the component renders a loading placeholder first, then fetches its real content automatically as soon as the page loads.\n\n  \n```liquid\n\n  {% component \"checkout/shipping_rates/page\", defer: true %}\n  ```\n\n\n- **`lazy`** — the component renders empty and only fills in when one of its `reload` events fires. Use it for content that should not appear until something happens.\n\n  \n```liquid\n\n  {% component \"cart\", reload: \"sc.cart-updated\", lazy: true %}\n  ```\n\n\n## Persisting data across reloads with `context`\n\nParameters you pass to a component are only available on the **first** render. When a component reloads from the server, it no longer has access to those parameters. The reload request only carries the component's stored context.\n\nTo keep a value available across reloads, store it with the [`context` tag](context-tag-reference). The context is saved in the component's encrypted token and restored on every reload.\n\nThe built-in order summary component demonstrates this pattern. On first render it receives a `source` parameter and saves an identifier into the context; on reload it reads that identifier back from the context and re-queries the record:\n\n\n```liquid\n\n{% liquid\n  default source: nil\n\n  if source == nil\n    # A reload: no parameters, so rebuild from stored context\n    case context.source_object\n      when \"Cart\"\n        query \"s_c__cart__c\" as results, s_c__sc_id__c: context.source_id\n      when \"Order\"\n        query \"order\" as results, s_c__sc_id__c: context.source_id\n    endcase\n    if results and results.size \u003e 0\n      assign source = results.first | cast: context.source_object\n    endif\n  else\n    # First render: store what we need for later reloads\n    capture source_object\n      echo source\n    endcapture\n    context source_object: source_object, source_id: source.id\n  endif\n-%}\n```\n\n\n## Knowing whether a component is reloading\n\nA `reloaded` variable is available inside the component. It is `false` on the first render and `true` on every subsequent server reload. Use it to skip work that only needs to happen once:\n\n\n```liquid\n\n{%- unless reloaded == true %}\n  {%- comment %} runs on first render only {% endcomment %}\n{%- endunless %}\n```\n\n\n## Showing flash messages after a reload\n\nWhen an event triggers a reload, you can also show an alert or notice by including a `data` object in the event detail. StoreConnect reads `alert`, `notice`, or `flash` from the event and dispatches the matching `sc.alert` or `sc.notice` message. This lets a single interaction both refresh a component and surface feedback to the shopper.\n\n## How it works\n\nUnderstanding the request cycle helps when debugging:\n\n1. On first render, StoreConnect renders the component inline and wraps it in a container that carries an encrypted token. The token holds the component name, its stored context, the shopper's session, and the list of reload events.\n2. The client watches the page for the events named in `reload`. When one fires (or immediately, for a deferred component), it sends the token to StoreConnect.\n3. StoreConnect decrypts the token, checks that it belongs to the current session, re-renders the component with `reloaded: true` and the restored context, and returns the fresh markup, which the client swaps into place.\n\nBecause the token is tied to the shopper's session, a component reload cannot be triggered on behalf of another session."}