# Custom Components for Shopify App Blocks

# Introduction

If you have specific requirements for your product card or product listing pages, or you just want to create a feature that we haven't thought of yet, you can create a Custom Component in the Product Card Builder.

To begin, simply drag the Custom component from the right sidebar into a Product Card block:

Product Card Builder with a Custom Component
Product Card Builder with a Custom Component

The Component Name is the crucial setting to tell the product card which HTML Web Component to render and should match your component's defintion, such as:

customElements.define("rcc-custom-component", ProductCustomComponent);

# Custom Component Example

Each component will automatically return Shopify product data including as price, product tags, variants, and more. The code example below will log the product data to your console from the this._product object - this is excellent for troubleshooting or seeing the full capabilities of Shopify:

rcc-custom-component.js
(function () {
    "use strict";
  
    class ProductCustomComponent extends HTMLElement {
      constructor() {
        super();
      }
  
      static get observedAttributes() {
        return ["product"];
      }
  
      get product() {
        return this._product;
      }
  
      set product(value) {
        this._product = value;
        this.render();
      }
  
      connectedCallback() {
        if (this._product) {
          this.render();
        }
      }
  
      render() {
        console.log(this._product);

        this.innerHTML = `
          <div class="product-custom-component">
            Example Product 
          </div>
          `;
      }
    }
  
    customElements.define("rcc-custom-component", ProductCustomComponent);
  })();

When adding custom component JS files to your theme, make sure to include them in your theme.liquid file before the App Block renders:

theme.liquid
{%- if request.page_type == 'search' or request.page_type == 'collection' %}
    {{ 'rcc-custom-component.js' | asset_url | script_tag }}
{%- endif %}

# Fetching Custom Data and Metafields

If you need to fetch Metafields that belong to the Product object in Shopify, we provide a simple way of fetching these values on render. Simply provide one or more Keys and associated Namespaces in the Product Card Builder.

These will then become available in this._product.metafields

Because Web Components are JavaScript, you also have full access to the fetch function in case you need to fetch any additional data, or even create POST requests for custom add to cart functions etc.

# Fetching Data from Shopify's Storefront API

There are times when the data from this._product is not complete enough for rendering modals or quick view containers. In this case you may need to fetch data from the Shopify Storefront API. The official Shopify documentation contains all of the potential data available to you:

Shopify GraphQL Storefront API
https://shopify.dev/docs/api/storefront/latest
Shopify Product Object
https://shopify.dev/docs/api/storefront/latest/objects/Product

Below is an example of a function that fetches data from the Shopify's Storefront API. Note this is an async function, so it requires an await e.g. await this.getVariantRRP() and if used inside the render function in the example above, will also need to be merged.

rcc-custom-component.js
async getVariantRRP() {
    if (!this._product?.variantId) {
      return null;
    }

    const token = document.querySelector(".rcc-search")?.dataset.token;
    if (!token) {
      console.warn("Storefront API token not found");
      return null;
    }

    const variantGid = `gid://shopify/ProductVariant/${this._product.variantId}`;

    const query = `
      query getVariantMetafield($id: ID!) {
        node(id: $id) {
          ... on ProductVariant {
            metafield(namespace: "custom", key: "variant_rrp") {
              value
            }
          }
        }
      }
    `;

    try {
      const response = await fetch("/api/2025-07/graphql.json", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-Shopify-Storefront-Access-Token": token,
        },
        body: JSON.stringify({
          query,
          variables: { id: variantGid },
        }),
      });

      const data = await response.json();
      return data?.data?.node?.metafield?.value || null;
    } catch (error) {
      console.error("Error Fetching Variant RRP:", error);
      return null;
    }
  }
}