Retrieving multiple products by ID using the AJAX API

Solved
keithpickering
Excursionist
13 1 13

Hi, long story short, I need to use the (non-admin) AJAX API to get data for products using only their ID. I would use liquid but I don't have access to the product's handles, so that's not an option. I only have the IDs - I said it's a long story haha

From what I can tell the best way to do this is to use the "suggestions" API for...not exactly its intended purpose.

This works perfectly for fetching one product at a time:

 

 

fetch(`/search/suggest.json?type=product&q=id:${id}&resources[type]=product`).then(data => {
  console.log(data)
});

 

 

But it would be a huge waste of HTTP requests if I had to do this for every product on this page - not the end of the world, but very unideal. 

I'm wondering if there's a way for me to pass multiple IDs to return all the products at once. I can't find any documentation whatsoever for this "q" parameter other than it's supposed to be the query, but there's no syntax given for how the query should work. I tried passing `ids` instead of `id` with a comma-delimited list, and while the request went through, it came back with zero results. All other formats I've tried have resulted in a 500 error from the request.

Thanks in advance!

kenput3r
Shopify Partner
41 6 13

Can you put all of the products in a collection and fetch the whole collection using graphql?

0 Likes
keithpickering
Excursionist
13 1 13

No graphql unfortunately, I'm working with a regular Shopify theme so all I have is liquid and JS.

0 Likes
kenput3r
Shopify Partner
41 6 13

@keithpickering You can create the collection though, right? I may have a couple of options for you.

0 Likes
keithpickering
Excursionist
13 1 13

Yeah I can create a collection. It's a little cumbersome since we're already using a separate app for bundling the products (and it stores the bundle products by ID in some shop metafields) but it wouldn't be the end of the world. 

0 Likes
kenput3r
Shopify Partner
41 6 13

@keithpickering you can fetch graphql using vanilla Javascript. You will need to create a private app within your Shopify store by visiting <your-store>.myshopify.com/admin/apps/private. When you create the app, make sure that the only permission checked under Storefront API Permissions is Read products, variants, and collections. You can then do something like below:

const api_url = 'https://your-store.myshopify.com/api/2020-07/graphql';
const headers = new Headers({
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'X-Shopify-Storefront-Access-Token': 'your-access-token'
});

const getShopifyProducts = async () => {
  const response = await fetch(api_url, {
    method: 'POST',
    headers: headers,
    body: JSON.stringify({query: query()})
  });
  const Shop = await response.json();
  displayProducts(Shop.data.collectionByHandle.products.edges)
}

const query = () => `
  {
    shop {
      name
      primaryDomain {
        url
        host
      }
    }
    collectionByHandle(handle: "pomades") {
      id
      products(first: 10) {
        edges {
          node {
            title
            id
            priceRange {
              maxVariantPrice {
                amount
              }
              minVariantPrice {
                amount
              }
            }
            images(first: 5) {
              edges {
                node {
                  originalSrc
                  altText
                }
              }
            }
            variants(first: 100) {
              edges {
                node {
                  title
                  id
                  priceV2 {
                    amount
                  }
                  image {
                    originalSrc
                    altText
                  }
                }
              }
            }
          }
        }
      }
    }
  }
`

Above code running in a Code Pen 

Another option is to create an alternate collection view that doesn't render a layout using the {% layout none %} liquid tag. You can then fetch a string of html that you can append to another piece of html. This is a bit hacky, but I have done it. You can see it setup here. By requesting your-store.com/collections/collection-handle?view=products (products is the name of my alternate template), Shopify responds with a page that doesn't have any of your apps, styles or any other dependencies that are loaded in the regular layout.liquid file.

 

PaulNewton
Shopify Partner
2576 136 457

You could also put the products into navigation menus and output specific pages in a <script> or in an alternate template.

Though making premade collections can be the sanest route since we cannot generate frontend collections.

For more than a handful of products use automatic collection based on tags.

shopify.com/collections/collectionname/products.json

 

Otherwise set an alternate template with no layout on /search and parse the terms returning text in json (cannot set mime type)

https://shopify.com/search?q=1234567890+0987654321&view=ajax

https://shopify.dev/docs/themes/liquid/reference/objects/search#search-terms

I can't find any documentation whatsoever for this "q" parameter other than it's supposed to be the query, but there's no syntax given for how the query should work. I tried passing `ids` instead of `id` with a comma-delimited list, and while the request went through, it came back with zero results. All other formats I've tried have resulted in a 500 error from the request.

If your up for experimenting with the q param observe other endpoints that use square brackets such as the /add endpoint

add/?items[0][id]=1234567890&items[0][quantity]=1&items[1][id]=0987654321&items[1][quantity]=1

 

 

Problem Solved? ✔️Accept and ? Like the solution so you can help others.
Buy me a coffee ☕ paypal.me/paulnewton or donate to eff.org
Confused? Busy? Buy a custom solution paull.newton+shopifyforum@gmail.com
0 Likes
keithpickering
Excursionist
13 1 13

This is an accepted solution.

Thanks for the tip about GQL, I had no idea and it's really put me in the right direction. The documentation for this stuff hasn't helped me too much, but with a bunch of trial and error I have found a GQL query that allows me to obtain products by ID. The clincher is using `btoa` to encode the GID format into a base64 string, since the Storefront API doesn't seem to recognize the regular GIDs.

const gids = ids.map(id => btoa(`gid://shopify/Product/${id}`));
return `
  nodes(ids: ${JSON.stringify(gids)}) {
    ...on Product {
      id
      title
    }
  }
}
`;
spencer_m
New Member
1 0 0

@keithpickering.  Solution is the correct solution.  Even if the product id you are using is already base64 encoded you still have to run it through btoa() otherwise you still get the bad id used message.

0 Likes