DOPP API: Theme Interop Tutorial
Introduction:
This tutorial demonstrates how to dynamically update prices and display discounts in custom product grids and containers using the DOPP API’s theme interop features.
Use Case/Context:
Let's say you have a wishlist page, where customers can view a list of items they have personally curated. Our app does not support wishlists out of the box, as there is too much potential variation.
The DOPP API’s themeInterop API makes it possible for you to easily display discount strikethrough prices in your wishlist.
Assumptions:
Before you start, make sure:
- You understand basic HTML, JavaScript, and Shopify’s Liquid syntax.
- The "Discounts Embed" app embed is enabled.
- You can modify Shopify theme files.
- Your products are displayed within a product grid element, with the ID wishlist-root.
- You have a wishlist_items Liquid variable, of type product_list.
Step 1: Converting Your Products to DOPPPublicApiProduct
First, prepare your products in the DOPPPublicApiProduct format using this Liquid snippet:
var wishlistItems = [
{% for dopp_product in wishlist_items %}
{%- liquid
assign current_variant = dopp_product.selected_or_first_available_variant
assign target = dopp_product.selected_or_first_available_variant
assign compare_at_price = target.compare_at_price
assign price = target.price
-%}
{
// Required fields
productId: {{ dopp_product.id | json }},
regularPriceInCents: {{ price | json }},
variantId: {{ current_variant.id | json }},
// Optional fields, but if your discount depends on any of these, they
// must be included
collectionIds: {{ dopp_product.collections | map: "id" | json }},
compareAtPriceInCents: {{ compare_at_price | json }},
handle: {{ dopp_product.handle | json }},
tags: {{ dopp_product.tags | json }},
url: {{ dopp_product.url | json }},
vendor: {{ dopp_product.vendor | json }},
variants: [
{% for variant in dopp_product.variants %}
{
id: {{ variant.id | json }},
title: {{ variant.title | json }},
priceInCents: {{ variant.price | json }},
compareAtPriceInCents: {{ variant.compare_at_price | json }},
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}{% unless forloop.last %},{% endunless %}
{% endfor %}
];
Step 2: Using Theme Interop API to Detect Product Grid Cells
Use themeInterop.findProductGridCells to detect product elements within #wishlist-root and correlate them with DOPPPublicApiProduct data. This function is ideal for product grids like wishlists or collections.
const gridCells = await doppApi.themeInterop.findProductGridCells(document.querySelector('#wishlist-root'), wishlistItems, 'COLLECTION_PAGE');
Step 3: Updating On-Page Prices Using Theme Interop API
Apply the themeInterop.updateOnPagePrices method to dynamically update displayed prices. While this method is used here following findProductGridCells, it can independently update prices for any product displayed within a given container, such as a single featured product.
for (const cell of gridCells) {
await doppApi.themeInterop.updateOnPagePrices(cell.element, 'COLLECTION_PAGE', cell.product);
}
Putting It All Together
Here’s how to integrate these steps into your Shopify theme to ensure dynamic price updates:
var wishlistItems = [
{% for dopp_product in wishlist_items %}
{%- liquid
assign current_variant = dopp_product.selected_or_first_available_variant
assign target = dopp_product.selected_or_first_available_variant
assign compare_at_price = target.compare_at_price
assign price = target.price
-%}
{
// Required fields
productId: {{ dopp_product.id | json }},
regularPriceInCents: {{ price | json }},
variantId: {{ current_variant.id | json }},
// Optional fields, but if your discount depends on any of these, they
// must be included
collectionIds: {{ dopp_product.collections | map: "id" | json }},
compareAtPriceInCents: {{ compare_at_price | json }},
handle: {{ dopp_product.handle | json }},
tags: {{ dopp_product.tags | json }},
url: {{ dopp_product.url | json }},
vendor: {{ dopp_product.vendor | json }},
variants: [
{% for variant in dopp_product.variants %}
{
id: {{ variant.id | json }},
title: {{ variant.title | json }},
priceInCents: {{ variant.price | json }},
compareAtPriceInCents: {{ variant.compare_at_price | json }},
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}{% unless forloop.last %},{% endunless %}
{% endfor %}
];
document.addEventListener('DOMContentLoaded', function() {
async function updateWishlistPrices() {
if (!window.RegiosDOPP || !window.RegiosDOPP.api || !window.RegiosDOPP.api.v0) {
console.error('DOPP API is not initialized');
return;
}
const api = window.RegiosDOPP.api.v0;
const wishlistRoot = document.querySelector('#wishlist-root');
const gridCells = await api.themeInterop.findProductGridCells(wishlistRoot, window.wishlistItems, 'COLLECTION_PAGE');
for (const cell of gridCells) {
await api.themeInterop.updateOnPagePrices(cell.element, 'COLLECTION_PAGE', cell.product);
}
}
updateWishlistPrices();
});
Your Feedback Matters
As a solo founder, your experience is crucial to me. Could you spare a moment to share your thoughts? Please leave a review on the Shopify App Store. Thank you for helping me improve!
Updated on: 28/12/2024
Thank you!