Creating a dynamically-prcied bundle using the API

Add custom line item properties during checkout to enable Recharge to identify and process dynamically priced bundles.

This guide explains how to create a dynamically-priced bundle using the Recharge API.


Requirements

Data needed

You need the following values to build the line item properties:

  • From the bundle product:
    • handle
    • Product ID
    • Variant ID
  • From the line item
    • Collection ID

Properties to add

Each line item must include the following properties:

Property

Description

_rc_bundle

\[nanoid]:\[product\_id]

  • This property consists of a nanoId of 9 characters and the bundle product ID separated by a colon

_rc_bundle_parent

The product handle

_rc_bundle_variant

The bundle product variant

_rc_bundle_collection_id

The Collection ID associated with the line item


Set-up instructions

Step 1 - Retrieve the bundle product data

Use the following script to fetch the required product data from Shopify:

const fetch = require('node-fetch');

// Replace with your actual store info and access token
const SHOPIFY_STORE = 'your-store-name.myshopify.com';
const ACCESS_TOKEN = 'your-admin-api-access-token';
const PRODUCT_ID = 'gid://shopify/Product/1234567890';

async function getProductDetails(productGID) {
  const query = `
    query getProduct($id: ID!) {
      product(id: $id) {
        id
        handle
        variants(first: 1) {
          edges {
            node {
              id
            }
          }
        }
      }
    }
  `;

  const response = await fetch(`https://${SHOPIFY_STORE}/admin/api/2024-01/graphql.json`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Shopify-Access-Token': ACCESS_TOKEN,
    },
    body: JSON.stringify({
      query,
      variables: { id: productGID }
    }),
  });

  const result = await response.json();

  if (result.errors) {
    console.error('GraphQL errors:', result.errors);
    return null;
  }

  const product = result.data.product;
  return {
    id: product.id,
    handle: product.handle,
    variants: product.variants.edges.map(edge => edge.node),
  };
}

// Run the function
getProductDetails(PRODUCT_ID).then(product => {
  if (product) {
    console.log(JSON.stringify(product, null, 2));
  } else {
    console.log('Product not found or error occurred.');
  }
});

Step 2 - Build line item properties

Use the function below to generate the correct property format for each line item:

import { nanoid } from 'nanoid';
function buildLineItemProperties(productId, productVariantId, productHandle, lineItemCollectionId, lineItemVariantId) {
    let itemData = {
        id: lineItemVariantId,
        quantity: 1,
        properties: {
            "_rc_bundle": `${nanoid(9)}:${productId}`,
            "_rc_bundle_parent": productHandle,
            "_rc_bundle_variant": productVariantId, // Important, this is the active variant ID for the bundle
            "_rc_bundle_collection_id": lineItemCollectionId,
        }
    };
    return itemData;
}

Step 3 - Update the cart

Use this script to post the updated line items to Shopify's cart endpoint:

queue = [];
const productId = "{productId}";
const productVariantId = "{productVariantId}";
const productHandle = "{product-handle}";
const lineItemCollectionId = "{lineItemCollectionId}";
const lineItems = buildLineItemProperties()
const lineItemVariantId = "{lineItemVariantId}";

const linetItemProperties = buildLineItemProperties(productId, productVariantId, productHandle, lineItemCollectionId, lineItemVariantId);
queue.push(lineItemProperties);

try {
  await dispatch('postToCart', { items: queue });
} catch (error) {
  console.log("error");
}

const postToCart = (data) => {
  return fetch('/cart/add.js', {
    headers: { 'Content-Type': 'application/json' },
    method: 'POST',
    body: JSON.stringify(data),
  });
};

📘

Note

This example updates the cart within the storefront context. If using a different context (e.g., headless implementation or server-side processing), adjust the script accordingly to ensure correct behavior.


Example results

The example below illustrates the expected structure for line item: