Product

An easy way to access and use Shopify Product data within the Superfans SDK.

Description

The product variable provides details about the product on a Product Detail (PDP) page. It includes the product ID, title, handle, description, images, options, variants, collections, metafields, and the currently selected variant.

This object is only available on PDP pages. Outside of a PDP context, it is null.

On mobile app initial load, selectedVariant may be null. If it is missing, use the first available variant from product.variants. Check availability on the variant with variant.availableForSale.

Properties of product

PropertyTypeScopeDescriptionExample
product.idStringPDPUnique id of the product.1234567890
product.productTypeStringPDPShopify product type. Can be an empty string.empty
product.handleStringPDPUser-friendly slug used in the product URL.sample-product
product.titleStringPDPName of the product.Sample product
product.descriptionStringPDPHTML description of the product.<p>Product description</p>
product.vendorStringPDPName of the vendor or brand.Brand
product.imagesString[]PDPArray of product image URLs.See sample product object
product.tagsString[]PDPArray of Shopify tags attached to the product.See sample product object
product.availableforSaleBooleanPDPWhether the product is available for purchase. The live key is availableforSale (lowercase f).true
product.selectedVariantObjectPDPCurrently selected variant. Can be null on initial mobile load. Same shape as a variants entry.See properties of variants
product.variantsObject[]PDPAll product variants.See properties of variants
product.optionsObject[]PDPProduct option definitions. Each entry has id, name, and optionValues.See sample product object
product.collectionsObject[]PDPCollections this product belongs to. Each entry has id, title, and handle.See sample product object
product.metafieldsObjectPDPMap of metafield handles to values. Missing metafields are null.See sample product object
product.klaviyoObjectPDPKlaviyo state: enabled, isOutOfStock, and isSubscribed.See sample product object

Properties of variants

product.selectedVariant uses this same shape when it is present.

PropertyTypeScopeDescriptionExample
product.variants.idStringPDPUnique id of the variant.1111111111
product.variants.titleStringPDPDisplay name of the variant.Black
product.variants.priceStringPDPPrice as a string, not a number.110.0
product.variants.imageStringPDPSingle image URL for the variant. This is not an array.https://cdn.shopify.com/image.jpg
product.variants.skuStringPDPStock keeping unit. Can be null.null
product.variants.quantityAvailableIntegerPDPInventory quantity available for the variant.100
product.variants.availableForSaleBooleanPDPWhether this variant can be purchased. Use this field. Do not use isAvailable.true
product.variants.currencyCodeStringPDPISO currency code for the variant price.USD
product.variants.selectedOptionsObject[]PDPOption name and value pairs selected for this variant. Each entry has name and value.See sample product object
product.variants.sellingPlanAllocationsObject[]PDPSelling plan allocations for the variant. Empty array when the variant has no selling plans.See properties of sellingPlanAllocations

Properties of sellingPlanAllocations

Use sellingPlanId as-is when calling addToCart or buyNow.

PropertyTypeScopeDescriptionExample
product.variants.sellingPlanAllocations.sellingPlanIdStringPDPShopify selling plan GID. Always starts with gid://shopify/SellingPlan/.gid://shopify/SellingPlan/selling_plan_id
product.variants.sellingPlanAllocations.labelStringPDPDisplay name of the selling plan.Deliver every month
product.variants.sellingPlanAllocations.intervalCountIntegerPDPBilling interval count. Can be null.1
product.variants.sellingPlanAllocations.intervalUnitStringPDPBilling interval unit, such as MONTH. Can be null.MONTH
product.variants.sellingPlanAllocations.priceAmountNumberPDPSubscription price amount.99
product.variants.sellingPlanAllocations.compareAtAmountNumberPDPCompare-at amount used for savings. Can be 0.110
product.variants.sellingPlanAllocations.perDeliveryAmountNumberPDPPer-delivery price amount.99
product.variants.sellingPlanAllocations.currencyCodeStringPDPISO currency code for the plan prices.USD
product.variants.sellingPlanAllocations.percentageDiscountIntegerPDPPercentage discount versus compare-at. Can be 0.10
product.variants.sellingPlanAllocations.checkoutChargeAmount.amountNumberPDPAmount charged at checkout.99
product.variants.sellingPlanAllocations.checkoutChargeAmount.currencyCodeStringPDPISO currency code for the checkout charge.USD

Sample product object

{"id":"1234567890","productType":"","handle":"sample-product","title":"Sample product","description":"<p>Product description</p>","vendor":"Brand","images":["https://cdn.shopify.com/image.jpg"],"tags":["new"],"availableforSale":true,"metafields":{"custom_key":null},"klaviyo":{"enabled":false,"isOutOfStock":false,"isSubscribed":false},"collections":[{"id":"123456789","title":"Sample collection","handle":"sample-collection"}],"options":[{"id":"gid://shopify/ProductOption/option_id","name":"Color","optionValues":[{"id":"gid://shopify/ProductOptionValue/option_value_id","name":"Black","swatch":{"color":"#000000","image":null}}]}],"selectedVariant":{"id":"1111111111","title":"Black","price":"110.0","image":"https://cdn.shopify.com/image.jpg","sku":null,"quantityAvailable":100,"availableForSale":true,"currencyCode":"USD","selectedOptions":[{"name":"Color","value":"Black"}],"sellingPlanAllocations":[{"sellingPlanId":"gid://shopify/SellingPlan/selling_plan_id","label":"Deliver every month","intervalCount":1,"intervalUnit":"MONTH","priceAmount":99,"compareAtAmount":110,"perDeliveryAmount":99,"currencyCode":"USD","percentageDiscount":10,"checkoutChargeAmount":{"amount":99,"currencyCode":"USD"}}]},"variants":[{"id":"1111111111","title":"Black","price":"110.0","image":"https://cdn.shopify.com/image.jpg","sku":null,"quantityAvailable":100,"availableForSale":true,"currencyCode":"USD","selectedOptions":[{"name":"Color","value":"Black"}],"sellingPlanAllocations":[{"sellingPlanId":"gid://shopify/SellingPlan/selling_plan_id","label":"Deliver every month","intervalCount":1,"intervalUnit":"MONTH","priceAmount":99,"compareAtAmount":110,"perDeliveryAmount":99,"currencyCode":"USD","percentageDiscount":10,"checkoutChargeAmount":{"amount":99,"currencyCode":"USD"}}]}]}

Example Usage

const product = Superfans.variables.product;

if (product) {
  const variant = product.selectedVariant || product.variants?.[0];
  console.log("Product: " + product.title);

  if (variant) {
    console.log("Variant: " + variant.title);
    const sellingPlanId = variant.sellingPlanAllocations?.[0]?.sellingPlanId;
    if (sellingPlanId) {
      console.log("Selling plan GID: " + sellingPlanId);
    }
  }
} else {
  console.log("Not on a product page.");
}

Best Practices

  1. Check for null: product is only defined on PDP pages.
  2. Re-read live product data: Inside Superfans.listeners.onVariantChanged, read Superfans.variables.product again instead of using a cached product or variant.
  3. Handle a null selected variant: On initial mobile load, fall back to product.variants[0].
  4. Pass selling plan GIDs as-is: Copy sellingPlanAllocations[].sellingPlanId into addToCart or buyNow. Do not strip gid:// or pass a numeric id.
  5. Read-only data: Do not modify product or variant objects.

Caveats

  1. Scope limited to PDP: product is null on any page that is not a product detail page.
  2. Product vs variant availability keys: The product uses availableforSale (lowercase f). Each variant uses availableForSale.
  3. Variant image is a string: variants[].image is one URL, not an array of URLs.
  4. Selling plans: sellingPlanAllocations is an array on each variant. sellingPlanId is a Shopify GID (gid://shopify/SellingPlan/...). The array is empty when the variant has no selling plans.

Did this page help you?