npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

liquid-section-renderer

v0.1.2

Published

A web component that simplifies using Shopify's Section Rendering API.

Readme

Liquid Section Renderer

A Web Component that utilizes Shopify's Section Rendering API to dynamically render Shopify sections via AJAX requests. For those that are newer to the Section Rendering API, when should you consider using it? There are two most common scenarios that often overlap that include the following:

  • To avoid redundant logic between Liquid and JavaScript (eg. product price display)
  • Some data is easier accessible in Liquid with linked objects such as products and variants

Browser Support

This component works in all modern browsers. For older browser support, include the following polyfills:

  • Custom Elements: Include @webcomponents/custom-elements
  • URL/URLSearchParams: Include url-polyfill for IE11 support

Installation

NPM

See the following NPM page for more information.

npm install liquid-section-renderer
yarn add liquid-section-renderer

To import into your project:

import 'liquid-section-renderer';

Manual

Copy the contents of liquid-section-renderer/dist/liquid-section-renderer.min.js into your project into the assets/liquid-section-renderer.js directory. Then include the JS file into your theme as follows:

<script src="{{ 'liquid-section-renderer.js' | asset_url }}" defer></script>

Examples

Basic Usage

In the below example, this component finds the closest parent with the class shopify-section and replaces the section, including the <liquid-section-renderer> element. It also infers that to use the current page's pathname to fetch content from. If you wish to be more specific in what is replaced, then see the following examples.

<section id="shopify-section-template--12345678909876__main" class="shopify-section section">
  <!-- Section content before : copy from here -->
  <liquid-section-renderer>
    <button trigger>
      Click to replace Shopify section
    </button>
  </liquid-section-renderer>

  <!-- Section content after : copy to here -->
</section>

Render Specific URL

In the below example, this component will make a request to the specified URL using the render-url attribute. As well as specifying which section file (eg. sections/main-product) to get the data from, and where in the DOM to replace the content using the destination attribute. This is useful if you want to get specific content such as product data from a single product.

<liquid-section-renderer
  render-url="/products/example-product?variant=10101010"
>
  <button
    trigger
    section="main-product"
    destination="#product-content"
  >
    Update Product
  </button>

  <div id="product-content">
    <!-- Content replaced here -->
  </div>
</liquid-section-renderer>

Multiple Destination Updates

This example is similar to the last, but the updates attribute replaces the section and destination attributes. This allows you to fetch content from a single URL while fetching multiple sections and updating multiple destinations, each mapped individually. This is useful in scenarios such as using a variant selector to update price and badges separately, when updating the entire section would break events or other functionality.

<liquid-section-renderer
  render-url="/products/example-product?variant=10101010"
>
  <button
    trigger
    updates='[
      {"section": "product-info", "destination": "#product-info"},
      {"section": "product-recommendations", "destination": "#recommendations"}
    ]'
    update-mode="replace"
  >
    Update Multiple
  </button>

  <div id="product-info">
    <!-- Content replaced here -->
  </div>

  <div id="recommendations">
    <!-- Content replaced here -->
  </div>
</liquid-section-renderer>

Trigger on Page Initialization

In the following example, the component will trigger on page initialization. This is useful in scenarios such as using Shopify's Product Recommendations API. In this instance we would be looking for a section file named sections/render-product-recommendation, and the destination would be the trigger element itself.

<liquid-section-renderer
  render-url="{{ routes.product_recommendations_url }}?product_id={{ product.id }}&limit=4&intent=related"
>
  <div
    trigger-init
    section="render-product-recommendation"
    destination="[data-product-recommendations]"
    data-product-recommendations
  >
    <!-- Content will be rendered here -->
  </div>
</liquid-section-renderer>

Trigger with Intersection Observer

We can easily replace trigger-init with trigger-intersect to trigger the section update when the element becomes visible in the viewport. We can also use the intersect-margin attribute to specify in pixels how closer the element needs to be to the viewport to trigger the section update.

<liquid-section-renderer
  render-url="{{ routes.product_recommendations_url }}?product_id={{ product.id }}&limit=4&intent=related"
  intersect-margin="200"
>
  <div
    trigger-intersect
    section="render-product-recommendation"
    destination="[data-product-recommendations]"
    data-product-recommendations
  >
    <!-- Content will be rendered here -->
  </div>
</liquid-section-renderer>

Multiple Render URLS

In the following example demonstrates how the render-url can be set on the trigger element, allowing for interactions such as paginated collection pages where multiple URLs are needed.

<liquid-section-renderer>
  <button
    trigger
    render-url="{{ paginate_prev_url }}"
  >
    Load previous products
  </button>

  <!-- Products grid here -->

  <button
    trigger
    render-url="{{ paginate_next_url }}"
  >
    Load next products
  </button>
</liquid-section-renderer>

Dynamic Attribute Updates

The following examples demonstrates how the its possible to dynamically update attributes such as the render-url such as to use it with search. This example utilizes Alpine JS for the dynamic input data.

<liquid-section-renderer
  id="Search"
  x-data="{ query: '' }"
  :render-url="`{{ routes.predictive_search_url }}?q=${query}&resources[type]=product`"
  loading-selector="#searchInput"
  loading-class="opacity-50"
>
  <div class="max-w-screen-xl mx-auto flex flex-col items-center justify-center gap-4 py-6">
    <h3>Predictive Search</h3>

    <input
      name="q"
      id="searchInput"
      x-model="query"
      class="border rounded py-2 px-6 transition-[opacity,color]"
      placeholder="Search: product name"
      section="render-predictive-search"
      destination="#searchResult"
      update-mode="replace"
      trigger
    />

    <div id="searchResult" x-show="query.length > 0"></div>
  </div>
</liquid-section-renderer>

Parent Attributes

| Attribute | Type | Default | Description | |-----------|------|---------|-------------| | debounce | Integer | 300 | The time to wait in milliseconds before sending request after a trigger event. | | history-mode | String | replace | Controls URL history behavior. Accepts add/push, or replace. | | intersect-margin | Integer | 0 | Margin in pixels around the viewport for intersection observer triggers. Helps with lazy loading sections that are close to the viewport. | | intersect-threshold | Integer | 10 | Percentage (1-100) of element that needs to be visible to trigger intersection observer. | | id | String | random | A unique identifier for the component. | | loading-selector | String | none | Uses querySelector to find the loading element. If not set, no loading indicator will be shown. | | loading-class | String | none | Class to add to loading element while loading. If unset and a loading-selector is provided, the component will inline display: none. | | render-url | String | location.pathname | Specify the URL to request the section from. | | scoped | Boolean | true | If set false, querySelector is scoped the entire document, otherwise is scoped to the component. | | timeout | Integer | 5000 | The time to wait for a response in milliseconds before cancelling the request. | | update-url | String | none | Update the URL after section is updated. | | update-title | String | none | Update the page title if updating page URL. |

Trigger Attributes

| Attribute | Type | Default | Description | |-----------|------|---------|-------------| | destination | String | none | Uses querySelector for the element to update with new section content. | | query | String | none | Uses querySelector to find element within section. If not found, uses entire section. | | section | String | none | The file name reference of the section to render found in sections/<file-name>.liquid. | | trigger | Boolean | none | Determines which element triggers a section update. | | trigger-init | Boolean | none | Immediately runs at end of component initialization. | | trigger-intersect | Boolean | none | Triggers when element becomes visible in viewport based on intersection observer settings. | | intersect-once | Boolean | true | Controls whether the intersection observer trigger fires only once or every time it is intersecting. | | render-url | String | none | Override the parent component's render-url for this specific trigger. | | update-mode | String | replace | How the new section content is inserted. Accepts replace, append/after, or prepend/before. | | updates | Array | none | Array of section/destination pairs for updating multiple sections. |

Updates Array

The following are the included attributes within the updates array.

<button
  updates='[
    {
     "destination": "#SectionId",
     "section": "section-file-name",
     "updateMode": "replace",
     "query": "[data-items]"
    }
  ]'
>
  Trigger
</button>

Event Listeners

The component automatically binds appropriate events based on the trigger element as follows. To note, all events have event.preventDefault() applied to avoid unintended actions or form submissions.

| Element Type | Event | |-------------|-------| | button | click | | form | submit | | input | input | | select | change | | textarea | input | | * | click |

Window Events

The component dispatches the following events during the section rendering lifecycle. A randomly generated id is included in the detail object to differentiate events.

| Event Name | Description | |------------|-------------| | liquid-render-init | Fired when the component is initialized | | liquid-render-destroying | Fired at beginning of the component being destroyed | | liquid-render-started | Fired when a section render request begins | | liquid-render-ended | Fired after a section render request ends | | liquid-render-error | Fired when a section render request fails |

Error Handling

The component includes built-in error handling for the following scenarios:

  • If neither updates array nor both section and destination attributes are provided, it will infer the current section it is within
  • If the provided updates array structure is invalid, an error will be thrown
  • If a section render request fails or times out, a liquid-render-error event will be dispatched

Hiding Loading Selector on Page Load

If you have are not using classes to hide/show your loading element and wish for the component to hide it using inline display: none, you can use the cloak attribute to hide the loading element, before the component is initialized. Once the component is initialized, the cloak attribute will be removed from the loading element.

Apply the following CSS to your main stylesheet:

[cloak] {
  display: none;
}

Add the attribute on your loading element as follows:

<liquid-section-renderer
  loading-selector="#loading"
>
  <!-- Your content -->
  <div id="loading" cloak>Loading...</div>
</liquid-section-renderer>