Understand How Shopify’s Product Recommendations API Work

Hey there, fellow Shopify merchants and developers! Looking to give your online sales a much-needed boost? Well, you’re in luck! In this blog post, we’re going to dive into the world of product recommendations and understand how they work so you can use them on your Shopify stores. So, grab a cup of coffee and let’s get started!

Understanding Product Recommendation Intents

Shopify provides different product recommendations based on the “intent” of the customer that the merchant is targeting:

  • Related products
  • Complementary products

Let’s see what each of these means and how they’re different from each other.

Related products are products that are similar to the product the customer is interacting with. You can often see this type of product recommendation under sections titled :

  • You might also like
  • Consider a similar item
  • Products related to an item
  • Customers frequently viewed

Complementary products are, well… you guessed it, complementary products. You might find these products titled:

  • Frequently bought together
  • Pair it with
  • Customers Who Bought This Also Purchased
  • Recommended Add-Ons
  • Popular Bundles
  • Customers Also Liked
  • Enhance Your Purchase with These Items
  • Complete Your Set with These Products

Setting Up An Example Product Recommendation Request

Here is an example of a Python script and Shopify’s product recommendation.

This tutorial assumes you have created a Shopify Partner account, a test development app and a test development store. We’ll go over a few Python scripts to see what goes on under the hood in Shopify libraries.

Steps 1-5 consist of OAuth flow which enables your app to access Shopify’s API.

Step 1:

Firstly, we need to install the app on the dev store. This can be done on the Shopify Partner admin back end pretty easily. Refer to the screenshot below:


How to install a test app on a test store

Step 2:

Now, let’s start the authorization flow with Shopify. We’ll send a POST request to my store’s URL and get the access token.

Here is the URL:

https://SHOPIFY_STORE_DOMAIN.com/admin/oauth/authorize?client_id=<YOUR_CLIENT_ID>&scope=<SCOPES>&redirect_uri=<YOUR_REDIRECT_URI>&state=<RANDOM_STATE>

So you’ll need to replace:

  • YOUR_SHOP_DOMAIN: this is the shop_name.myshopify.com URL
  • REPLACE_THIS_WITH_YOUR_CODE: the Client ID

You can find the Client ID from the Client Credentials page on the Partners back end (refer to the screenshot below).

Client credentials

Tip: The redirection_uri needs to be whitelisted on App Setup in the Partners back end.
Tip 2: <RANDOM_STATE> is a random code to add to the request. Store this number as we’ll need it again for some verification.
Tip 3: Run the code below for generating RANDOM_STATE.

import secrets

random_state = secrets.token_urlsafe(16)

Step 3:

Once you post that URL in your browser, you’ll be redirected to the redirect_uri as specified in your POST.

Take a look at your redirect URL. There are some important parameters in it!

https://CALL_BACK_URL/auth/callback?code=9bb7a1c26d2b570ebcd3fa4cecd9922e&hmac=00aeea16a72bca506de4ba24a1ae3c637efa445bb17f41013933410033b1290b&host=YWRtaW4uc2hvcGlmeS5jb20vc3RvcmUvbWVobWV0cy1kZXY&shop=mehmets-dev.myshopify.com&state=6MMkx_60OqGjYVQK7_qr6g&timestamp=1686609587

Here are the parameters:

  • code: The authorization code you need to exchange for access and refresh tokens.
  • hmac: A message authentication code for data integrity verification.
  • host: The host of your app.
  • shop: The Shopify store’s domain.
  • state: The random state value you provided earlier.
  • timestamp: The timestamp of the request.

The most important is the “code”, which in the URL above is 9bb7a1c26d2b570ebcd3fa4cecd9922e.

Step 4:

Now, time to create a POST request using Python!

Here is an example code of a Python request script.

import requests
import json

# Replace these values with your actual client ID, client secret, and authorization code
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
authorization_code = "AUTHORIZATION_CODE"

# Construct the request payload
payload = {
    "client_id": client_id,
    "client_secret": client_secret,
    "code": authorization_code
}

# Make the POST request to the Shopify token endpoint
response = requests.post("https://mehmets-dev.myshopify.com/admin/oauth/access_token", json=payload)

# Parse the JSON response
data = response.json()

# Extract the access token and refresh token
access_token = data["access_token"]

# Print the tokens
print("Access Token:", access_token)

So access_token is what you need out of the response to your request.

Step 5:

Up until this step, we’ve worked through Shopify’s OAuth flow. Now we can create our request to Shopify’s API.

import requests
import json

# Replace these values with your actual access token and store URL
store_url = "mehmets-dev.myshopify.com"
product_id = "123123123123123"
limit = 4
intent = "related"
access_token = "ACCESS_TOKEN"

# Make a GET request to the Shopify API endpoint to retrieve product recommendations
url = f"https://{store_url}/en/recommendations/products.json?product_id={product_id}&limit={limit}&intent={intent}"
headers = {
    "X-Shopify-Access-Token": access_token
}
response = requests.get(url, headers=headers)

# Parse the JSON response
data = response.json()

# Process the data as needed
# ...

# Example: Print the retrieved product recommendations
for recommendation in data['recommendations']:
    print(recommendation['title'])

In the code above, we’re sending a request to the store’s URL using the access token that we acquired in the step prior. The access token goes into the header of the request.

Parameters:

  • product_id: This is the product_id that can be found on the merchant’s store backend
  • limit: You can limit the number of recommended products
  • intent: Only two possible values; related or complementary – explained in the first section

API Response

The response is a JSON list of the products recommended for the queried product.

The response consists of parameters such as id, name, description and many other things. This is so that the API’s response can directly be fed into Shopify themes or Shopify apps.

The full list of products keys in the products key:

['id', 'title', 'handle', 'description', 'published_at', 'created_at', 'vendor', 'type', 'tags', 'price', 'price_min', 'price_max', 'available', 'price_varies', 'compare_at_price', 'compare_at_price_min', 'compare_at_price_max', 'compare_at_price_varies', 'variants', 'images', 'featured_image', 'options', 'url', 'media', 'requires_selling_plan', 'selling_plan_groups']

An example of the response:

{
 "intent": "related",
 "products": [
   {
     "id": 35,
     "title": "Gorgeous Silk Coat",
     "handle": "gorgeous-silk-coat",
     "description": null,
     "published_at": "2019-02-26T11:34:58-05:00",
     "created_at": "2019-02-26T11:34:58-05:00",
     "vendor": "Marge Group",
     "type": "Outdoors",
     "tags": [],
     "price": 380000,
     "price_min": 380000,
     "price_max": 790000,
     "available": true,
     "price_varies": true,
     "compare_at_price": null,
     "compare_at_price_min": 0,
     "compare_at_price_max": 0,
     "compare_at_price_varies": false,
     "variants": [
       {
         "id": 69,
         "title": "Small Aluminum Knife",
         "option1": "Small Aluminum Knife",
         "option2": null,
         "option3": null,
         "sku": "",
         "requires_shipping": true,
         "taxable": true,
         "featured_image": null,
         "available": true,
         "name": "Gorgeous Silk Coat - Small Aluminum Knife",
         "public_title": "Small Aluminum Knife",
         "options": [
           "Small Aluminum Knife"
         ],
         "price": 790000,
         "weight": 9500,
         "compare_at_price": null,
         "inventory_management": "shopify",
         "barcode": null
       },
       {
         "id": 70,
         "title": "Heavy Duty Bronze Shoes",
         "option1": "Heavy Duty Bronze Shoes",
         "option2": null,
         "option3": null,
         "sku": "",
         "requires_shipping": true,
         "taxable": true,
         "featured_image": null,
         "available": true,
         "name": "Gorgeous Silk Coat - Heavy Duty Bronze Shoes",
         "public_title": "Heavy Duty Bronze Shoes",
         "options": [
           "Heavy Duty Bronze Shoes"
         ],
         "price": 380000,
         "weight": 2200,
         "compare_at_price": null,
         "inventory_management": "shopify",
         "barcode": null
       }
     ],
     "images": [],
     "featured_image": null,
     "options": [
       {
         "name": "Color or something",
         "position": 1,
         "values": [
           "Small Aluminum Knife",
           "Heavy Duty Bronze Shoes"
         ]
       }
     ],
     "url": "/products/gorgeous-silk-coat?pr_choice=default&pr_prod_strat=copurchase&pr_rec_pid=35&pr_ref_pid=17&pr_seq=alternating"
   },
   {
     "id": 13,
     "title": "Gorgeous Wooden Computer",
     "handle": "gorgeous-wooden-computer",
     "description": null,
     "published_at": "2019-02-26T11:34:15-05:00",
     "created_at": "2019-02-26T11:34:15-05:00",
     "vendor": "Purdy Inc",
     "type": "Garden",
     "tags": [],
     "price": 930000,
     "price_min": 930000,
     "price_max": 1730000,
     "available": true,
     "price_varies": true,
     "compare_at_price": null,
     "compare_at_price_min": 0,
     "compare_at_price_max": 0,
     "compare_at_price_varies": false,
     "variants": [
       {
         "id": 25,
         "title": "Mediocre Silk Bottle",
         "option1": "Mediocre Silk Bottle",
         "option2": null,
         "option3": null,
         "sku": "",
         "requires_shipping": true,
         "taxable": true,
         "featured_image": null,
         "available": true,
         "name": "Gorgeous Wooden Computer - Mediocre Silk Bottle",
         "public_title": "Mediocre Silk Bottle",
         "options": [
           "Mediocre Silk Bottle"
         ],
         "price": 1730000,
         "weight": 5700,
         "compare_at_price": null,
         "inventory_management": "shopify",
         "barcode": null
       },
       {
         "id": 26,
         "title": "Lightweight Paper Shirt",
         "option1": "Lightweight Paper Shirt",
         "option2": null,
         "option3": null,
         "sku": "",
         "requires_shipping": true,
         "taxable": true,
         "featured_image": null,
         "available": true,
         "name": "Gorgeous Wooden Computer - Lightweight Paper Shirt",
         "public_title": "Lightweight Paper Shirt",
         "options": [
           "Lightweight Paper Shirt"
         ],
         "price": 930000,
         "weight": 6600,
         "compare_at_price": null,
         "inventory_management": "shopify",
         "barcode": null
       }
     ],
     "images": [],
     "featured_image": null,
     "options": [
       {
         "name": "Color or something",
         "position": 1,
         "values": [
           "Mediocre Silk Bottle",
           "Lightweight Paper Shirt"
         ]
       }
     ],
     "url": "/products/gorgeous-wooden-computer?pr_choice=default&pr_prod_strat=description&pr_rec_pid=13&pr_ref_pid=17&pr_seq=alternating"
   }
 ]
}

Note: Shopify may return fewer recommendations than you expected. I saw many examples where the API only recommended one product or even none. These are usually stores with small or old data

Tracking Product Recommendations

You might want to track the traffic that engages with these recommendations. This data might help you find many insights. For example, at what stage of your website funnel do complementary offers work better? And when do related item offers work?

Shopify already appends some parameters to link in the recommendations they provide in their API. Here are the parameters:

  • pr_prod_strat=use_description
  • pr_rec_id=123123123
  • pr_rec_pid=123123123
  • pr_ref_pid=123123123
  • pr_seq=uniform

I couldn’t find any documentation on what each of these parameters refers to. So I don’t have the exact information. But we can always speculate!

I left the text values for the parameters from an example I have (and randomized the numeric values).

pr_prod_strat: this sounds like they’re testing a few strategies about using or not using the product description in the product recommendation itself.

We have two id values: pr_rec_id and pr_rec_pid. I believe this way you can refer to individual product recommendations to a single product recommendation response. This could come in handy in tracking what combinations of products convert better.

pr_seq: not sure what this refers to at all!

Extra parameters

We won’t go into much detail here on how to implement these extra parameters. These parameters can be added to the end of the link URL.

These parameters can refer to where the products are displayed. Imagine you display these products on another product page or a certain section of the homepage. It would be good to know which of these offers perform where and when.

Using Conversion Sets in Google Ads

It’s important to put conversions actions in sets with your Google ads set up. By default, Google Ads gives you several categories to work with. Some examples are:

  • Submit lead forms
  • Sign-ups
  • Contacts
  • Other
  • Page views

These goal categories are also grouped together. There are three of them.

  • Sales categories
  • Leads categories
  • More categories.

By putting your conversion actions into these groups, you give Google Ads information on what goals to prioritize when bidding for traffic.

You can also set value for your conversions, such as purchase actions. This would enable you to optimize for ROAS, for instance.

For more information on this, visit the blog in link below:

https://instapage.com/blog/conversion-action-sets