Last active
December 28, 2022 22:38
-
-
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 …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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