Skip to content

Instantly share code, notes, and snippets.

@Acen
Last active December 28, 2022 22:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Acen/3f23e64244ab490cf0dfbe1c49ceabcb to your computer and use it in GitHub Desktop.
Save Acen/3f23e64244ab490cf0dfbe1c49ceabcb to your computer and use it in GitHub Desktop.
Blog type of "testimonials" -> has articles with a metafield that links to a product ID. Builds a Map of products that have an articles array, with a list of articles that have that metafield relationship. Does 2 requests. One to get a list of the blog posts, then a batch request for products (using the "(id:<number>) OR (id:<number>)") request …
const authenticationHeaders = new Headers();
authenticationHeaders.append("Content-Type", "application/json");
authenticationHeaders.append("X-Shopify-Storefront-Access-Token", <access-token-here>);
const articleGraphql = JSON.stringify({
query: "query {\n blog(handle: \"testimonials\"){\n articles(first: 100){\n edges{\n node{\n id\n title\n url\n metafield(namespace: \"testimonial\", key: \"product\"){\n value }\n }\n }\n }\n }\n}",
variables: {}
});
const articleRequest = {
method: 'POST',
headers: authenticationHeaders,
body: articleGraphql,
redirect: 'follow'
};
const cleanGID = (gid) => {
return gid.split('/').pop();
}
const handleArticles = (result) => new Promise((resolve) => {
const product_id_list = [];
const edges = JSON.parse(result).data?.blog?.articles?.edges;
edges.map(node => {
node = node?.node;
const gid = node?.metafield?.value;
const id = cleanGID(gid);
product_id_list.push(`(id:${id})`);
})
resolve([[...new Set(product_id_list)], edges]);
})
const gidDecode = (str, clean = false) => {
const gid = str.includes('gid://') ? str : base64Decode(str);
if (!clean) {
return gid;
}
return cleanGID(gid);
}
const base64Decode = (str) => {
return decodeURIComponent(atob(str));
}
const mappedArticles = (articleNodeArray) => {
const map = new Map();
articleNodeArray.map(item => {
const productID = cleanGID(item.node.metafield.value);
if (map.has(productID)) {
map.set(productID, map.get(productID).push(item.node));
} else {
map.set(productID, [item.node].flat());
}
})
return map;
};
const buildProductList = (products, articleMap) => {
const productMap = new Map();
JSON.parse(products).data?.products?.edges.map(item => {
const productData = item.node;
const productGid = gidDecode(item.node.id, true)
productData.articles = articleMap.get(productGid);
productMap.set(gidDecode(item.node.id, true), productData);
})
return productMap;
}
const handleProductIDList = (product_id_list, articles) => {
const query = product_id_list.join(' OR ');
const cleanedArticles = mappedArticles(articles);
const productGraphQL = JSON.stringify({
query: `query {\n products(query: "${query}", first: 100) {\n edges {\n node {\n id\n handle\n featuredImage {\n url\n }\n metafield(namespace: \"my_fields\", key: \"dimensions\") {\n value\n }\n }\n }\n }\n}`,
});
const productRequest = {
method: 'POST',
headers: authenticationHeaders,
body: productGraphQL,
redirect: 'follow'
};
fetch("https://<shopify-shop-url>.myshopify.com/api/graphql", productRequest)
.then(response => response.text())
.then(result => {
const productMap = buildProductList(result, cleanedArticles);
console.log('map', productMap);
})
.catch(error => console.log('error', error));
}
fetch("https://<shopify-shop-url>.myshopify.com/api/graphql", articleRequest)
.then(response => response.text())
.then(result => handleArticles(result).then(([product_ids, articles] = data) => handleProductIDList(product_ids, articles)))
.catch(error => console.log('error', error));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment