diff --git a/components/product/ProductView/ProductView.tsx b/components/product/ProductView/ProductView.tsx
index f689030d6..aab6d0d19 100644
--- a/components/product/ProductView/ProductView.tsx
+++ b/components/product/ProductView/ProductView.tsx
@@ -61,29 +61,31 @@ const ProductView: FC<ProductViewProps> = ({ product, relatedProducts }) => {
           <ProductSidebar product={product} className={s.sidebar} />
         </div>
         <hr className="mt-7 border-accent-2" />
-        <section className="py-12 px-6 mb-10">
-          <Text variant="sectionHeading">Related Products</Text>
-          <div className={s.relatedProductsGrid}>
-            {relatedProducts.map((p) => (
-              <div
-                key={p.path}
-                className="animated fadeIn bg-accent-0 border border-accent-2"
-              >
-                <ProductCard
-                  noNameTag
-                  product={p}
+        {relatedProducts.length && (
+          <section className="py-12 px-6 mb-10">
+            <Text variant="sectionHeading">Related Products</Text>
+            <div className={s.relatedProductsGrid}>
+              {relatedProducts.map((p) => (
+                <div
                   key={p.path}
-                  variant="simple"
-                  className="animated fadeIn"
-                  imgProps={{
-                    width: 300,
-                    height: 300,
-                  }}
-                />
-              </div>
-            ))}
-          </div>
-        </section>
+                  className="animated fadeIn bg-accent-0 border border-accent-2"
+                >
+                  <ProductCard
+                    noNameTag
+                    product={p}
+                    key={p.path}
+                    variant="simple"
+                    className="animated fadeIn"
+                    imgProps={{
+                      width: 300,
+                      height: 300,
+                    }}
+                  />
+                </div>
+              ))}
+            </div>
+          </section>
+        )}
       </Container>
       <NextSeo
         title={product.name}
diff --git a/framework/commerce/api/operations.ts b/framework/commerce/api/operations.ts
index 2910a2d82..d67a8efbc 100644
--- a/framework/commerce/api/operations.ts
+++ b/framework/commerce/api/operations.ts
@@ -7,10 +7,11 @@ import type {
   GetAllProductPathsOperation,
   GetAllProductsOperation,
   GetProductOperation,
+  GetRelatedProductsOperation,
 } from '../types/product'
 import type { APIProvider, CommerceAPI } from '.'
 
-const noop = () => {
+const noop = (_props?: any) => {
   throw new Error('Not implemented')
 }
 
@@ -22,6 +23,7 @@ export const OPERATIONS = [
   'getCustomerWishlist',
   'getAllProductPaths',
   'getAllProducts',
+  'getRelatedProducts',
   'getProduct',
 ] as const
 
@@ -139,6 +141,22 @@ export type Operations<P extends APIProvider> = {
     ): Promise<T['data']>
   }
 
+  getRelatedProducts: {
+    <T extends GetRelatedProductsOperation>(opts: {
+      variables: T['variables']
+      config?: P['config']
+      preview?: boolean
+    }): Promise<T['data']>
+
+    <T extends GetAllProductsOperation>(
+      opts: {
+        variables: T['variables']
+        config?: P['config']
+        preview?: boolean
+      } & OperationOptions
+    ): Promise<T['data']>
+  }
+
   getProduct: {
     <T extends GetProductOperation>(opts: {
       variables: T['variables']
diff --git a/framework/commerce/types/product.ts b/framework/commerce/types/product.ts
index 6a68d8ad1..eb0b53e99 100644
--- a/framework/commerce/types/product.ts
+++ b/framework/commerce/types/product.ts
@@ -93,6 +93,16 @@ export type GetAllProductsOperation<T extends ProductTypes = ProductTypes> = {
   }
 }
 
+export type GetRelatedProductsOperation<
+  T extends ProductTypes = ProductTypes
+> = {
+  data: { products: T['product'][] }
+  variables: {
+    productId: string
+    first?: number
+  }
+}
+
 export type GetProductOperation<T extends ProductTypes = ProductTypes> = {
   data: { product?: T['product'] }
   variables: { path: string; slug?: never } | { path?: never; slug: string }
diff --git a/framework/shopify/api/operations/get-related-products.ts b/framework/shopify/api/operations/get-related-products.ts
new file mode 100644
index 000000000..ea60e277a
--- /dev/null
+++ b/framework/shopify/api/operations/get-related-products.ts
@@ -0,0 +1,74 @@
+import type {
+  OperationContext,
+  OperationOptions,
+} from '@commerce/api/operations'
+import { GetRelatedProductsOperation } from '../../types/product'
+import {
+  GetRelatedProductsQuery,
+  GetRelatedProductsQueryVariables,
+  Product as ShopifyProduct,
+} from '../../schema'
+import type { ShopifyConfig, Provider } from '..'
+import getRelatedProductsQuery from '../../utils/queries/get-related-products-query'
+import { normalizeProduct } from '../../utils'
+
+export default function getRelatedProductsOperation({
+  commerce,
+}: OperationContext<Provider>) {
+  async function getRelatedProductsOperation<
+    T extends GetRelatedProductsOperation
+  >(opts: {
+    variables: T['variables']
+    config?: Partial<ShopifyConfig>
+    preview?: boolean
+  }): Promise<T['data']>
+
+  async function getRelatedProductsOperation<
+    T extends GetRelatedProductsOperation
+  >(
+    opts: {
+      variables: T['variables']
+      config?: Partial<ShopifyConfig>
+      preview?: boolean
+    } & OperationOptions
+  ): Promise<T['data']>
+
+  async function getRelatedProductsOperation<
+    T extends GetRelatedProductsOperation
+  >({
+    query = getRelatedProductsQuery,
+    variables,
+    config,
+  }: {
+    query?: string
+    variables: T['variables']
+    config?: Partial<ShopifyConfig>
+    preview?: boolean
+  }): Promise<T['data']> {
+    const { fetch, locale } = commerce.getConfig(config)
+
+    const { data } = await fetch<
+      GetRelatedProductsQuery,
+      GetRelatedProductsQueryVariables
+    >(
+      query,
+      { variables },
+      {
+        ...(locale && {
+          headers: {
+            'Accept-Language': locale,
+          },
+        }),
+      }
+    )
+
+    return {
+      products:
+        data.productRecommendations
+          ?.map((product) => normalizeProduct(product as ShopifyProduct))
+          .splice(0, variables?.first || 4) ?? [],
+    }
+  }
+
+  return getRelatedProductsOperation
+}
diff --git a/framework/shopify/api/operations/index.ts b/framework/shopify/api/operations/index.ts
index 7872a20b6..f7fff903e 100644
--- a/framework/shopify/api/operations/index.ts
+++ b/framework/shopify/api/operations/index.ts
@@ -2,6 +2,7 @@ export { default as getAllPages } from './get-all-pages'
 export { default as getPage } from './get-page'
 export { default as getAllProducts } from './get-all-products'
 export { default as getAllProductPaths } from './get-all-product-paths'
+export { default as getRelatedProducts } from './get-related-products'
 export { default as getProduct } from './get-product'
 export { default as getSiteInfo } from './get-site-info'
 export { default as login } from './login'
diff --git a/framework/shopify/schema.d.ts b/framework/shopify/schema.d.ts
index 328f0ff1b..66236ab44 100644
--- a/framework/shopify/schema.d.ts
+++ b/framework/shopify/schema.d.ts
@@ -2635,7 +2635,7 @@ export type FulfillmentTrackingInfo = {
 
 /** Represents information about the metafields associated to the specified resource. */
 export type HasMetafields = {
-  /** The metafield associated with the resource. */
+  /** Returns a metafield found by namespace and key. */
   metafield?: Maybe<Metafield>
   /** A paginated list of metafields associated with the resource. */
   metafields: MetafieldConnection
@@ -3908,7 +3908,7 @@ export type Product = Node &
     images: ImageConnection
     /** The media associated with the product. */
     media: MediaConnection
-    /** The metafield associated with the resource. */
+    /** Returns a metafield found by namespace and key. */
     metafield?: Maybe<Metafield>
     /** A paginated list of metafields associated with the resource. */
     metafields: MetafieldConnection
@@ -4235,7 +4235,7 @@ export type ProductVariant = Node &
     id: Scalars['ID']
     /** Image associated with the product variant. This field falls back to the product image if no image is available. */
     image?: Maybe<Image>
-    /** The metafield associated with the resource. */
+    /** Returns a metafield found by namespace and key. */
     metafield?: Maybe<Metafield>
     /** A paginated list of metafields associated with the resource. */
     metafields: MetafieldConnection
@@ -5265,6 +5265,32 @@ export type GetAllProductPathsQuery = { __typename?: 'QueryRoot' } & {
   }
 }
 
+export type ListProductDetailsFragment = { __typename?: 'Product' } & Pick<
+  Product,
+  'id' | 'title' | 'vendor' | 'handle'
+> & {
+    priceRange: { __typename?: 'ProductPriceRange' } & {
+      minVariantPrice: { __typename?: 'MoneyV2' } & Pick<
+        MoneyV2,
+        'amount' | 'currencyCode'
+      >
+    }
+    images: { __typename?: 'ImageConnection' } & {
+      pageInfo: { __typename?: 'PageInfo' } & Pick<
+        PageInfo,
+        'hasNextPage' | 'hasPreviousPage'
+      >
+      edges: Array<
+        { __typename?: 'ImageEdge' } & {
+          node: { __typename?: 'Image' } & Pick<
+            Image,
+            'originalSrc' | 'altText' | 'width' | 'height'
+          >
+        }
+      >
+    }
+  }
+
 export type ProductConnectionFragment = { __typename?: 'ProductConnection' } & {
   pageInfo: { __typename?: 'PageInfo' } & Pick<
     PageInfo,
@@ -5272,31 +5298,7 @@ export type ProductConnectionFragment = { __typename?: 'ProductConnection' } & {
   >
   edges: Array<
     { __typename?: 'ProductEdge' } & {
-      node: { __typename?: 'Product' } & Pick<
-        Product,
-        'id' | 'title' | 'vendor' | 'handle'
-      > & {
-          priceRange: { __typename?: 'ProductPriceRange' } & {
-            minVariantPrice: { __typename?: 'MoneyV2' } & Pick<
-              MoneyV2,
-              'amount' | 'currencyCode'
-            >
-          }
-          images: { __typename?: 'ImageConnection' } & {
-            pageInfo: { __typename?: 'PageInfo' } & Pick<
-              PageInfo,
-              'hasNextPage' | 'hasPreviousPage'
-            >
-            edges: Array<
-              { __typename?: 'ImageEdge' } & {
-                node: { __typename?: 'Image' } & Pick<
-                  Image,
-                  'originalSrc' | 'altText' | 'width' | 'height'
-                >
-              }
-            >
-          }
-        }
+      node: { __typename?: 'Product' } & ListProductDetailsFragment
     }
   >
 }
@@ -5344,6 +5346,12 @@ export type CheckoutDetailsFragment = { __typename?: 'Checkout' } & Pick<
                   ProductVariant,
                   'id' | 'sku' | 'title'
                 > & {
+                    selectedOptions: Array<
+                      { __typename?: 'SelectedOption' } & Pick<
+                        SelectedOption,
+                        'name' | 'value'
+                      >
+                    >
                     image?: Maybe<
                       { __typename?: 'Image' } & Pick<
                         Image,
@@ -5498,84 +5506,95 @@ export type GetPageQuery = { __typename?: 'QueryRoot' } & {
   >
 }
 
+export type ProductDetailsFragment = { __typename?: 'Product' } & Pick<
+  Product,
+  | 'id'
+  | 'handle'
+  | 'availableForSale'
+  | 'title'
+  | 'productType'
+  | 'vendor'
+  | 'description'
+  | 'descriptionHtml'
+> & {
+    options: Array<
+      { __typename?: 'ProductOption' } & Pick<
+        ProductOption,
+        'id' | 'name' | 'values'
+      >
+    >
+    priceRange: { __typename?: 'ProductPriceRange' } & {
+      maxVariantPrice: { __typename?: 'MoneyV2' } & Pick<
+        MoneyV2,
+        'amount' | 'currencyCode'
+      >
+      minVariantPrice: { __typename?: 'MoneyV2' } & Pick<
+        MoneyV2,
+        'amount' | 'currencyCode'
+      >
+    }
+    variants: { __typename?: 'ProductVariantConnection' } & {
+      pageInfo: { __typename?: 'PageInfo' } & Pick<
+        PageInfo,
+        'hasNextPage' | 'hasPreviousPage'
+      >
+      edges: Array<
+        { __typename?: 'ProductVariantEdge' } & {
+          node: { __typename?: 'ProductVariant' } & Pick<
+            ProductVariant,
+            'id' | 'title' | 'sku' | 'availableForSale' | 'requiresShipping'
+          > & {
+              selectedOptions: Array<
+                { __typename?: 'SelectedOption' } & Pick<
+                  SelectedOption,
+                  'name' | 'value'
+                >
+              >
+              priceV2: { __typename?: 'MoneyV2' } & Pick<
+                MoneyV2,
+                'amount' | 'currencyCode'
+              >
+              compareAtPriceV2?: Maybe<
+                { __typename?: 'MoneyV2' } & Pick<
+                  MoneyV2,
+                  'amount' | 'currencyCode'
+                >
+              >
+            }
+        }
+      >
+    }
+    images: { __typename?: 'ImageConnection' } & {
+      pageInfo: { __typename?: 'PageInfo' } & Pick<
+        PageInfo,
+        'hasNextPage' | 'hasPreviousPage'
+      >
+      edges: Array<
+        { __typename?: 'ImageEdge' } & {
+          node: { __typename?: 'Image' } & Pick<
+            Image,
+            'originalSrc' | 'altText' | 'width' | 'height'
+          >
+        }
+      >
+    }
+  }
+
 export type GetProductBySlugQueryVariables = Exact<{
   slug: Scalars['String']
 }>
 
 export type GetProductBySlugQuery = { __typename?: 'QueryRoot' } & {
-  productByHandle?: Maybe<
-    { __typename?: 'Product' } & Pick<
-      Product,
-      | 'id'
-      | 'handle'
-      | 'title'
-      | 'productType'
-      | 'vendor'
-      | 'description'
-      | 'descriptionHtml'
-    > & {
-        options: Array<
-          { __typename?: 'ProductOption' } & Pick<
-            ProductOption,
-            'id' | 'name' | 'values'
-          >
-        >
-        priceRange: { __typename?: 'ProductPriceRange' } & {
-          maxVariantPrice: { __typename?: 'MoneyV2' } & Pick<
-            MoneyV2,
-            'amount' | 'currencyCode'
-          >
-          minVariantPrice: { __typename?: 'MoneyV2' } & Pick<
-            MoneyV2,
-            'amount' | 'currencyCode'
-          >
-        }
-        variants: { __typename?: 'ProductVariantConnection' } & {
-          pageInfo: { __typename?: 'PageInfo' } & Pick<
-            PageInfo,
-            'hasNextPage' | 'hasPreviousPage'
-          >
-          edges: Array<
-            { __typename?: 'ProductVariantEdge' } & {
-              node: { __typename?: 'ProductVariant' } & Pick<
-                ProductVariant,
-                'id' | 'title' | 'sku'
-              > & {
-                  selectedOptions: Array<
-                    { __typename?: 'SelectedOption' } & Pick<
-                      SelectedOption,
-                      'name' | 'value'
-                    >
-                  >
-                  priceV2: { __typename?: 'MoneyV2' } & Pick<
-                    MoneyV2,
-                    'amount' | 'currencyCode'
-                  >
-                  compareAtPriceV2?: Maybe<
-                    { __typename?: 'MoneyV2' } & Pick<
-                      MoneyV2,
-                      'amount' | 'currencyCode'
-                    >
-                  >
-                }
-            }
-          >
-        }
-        images: { __typename?: 'ImageConnection' } & {
-          pageInfo: { __typename?: 'PageInfo' } & Pick<
-            PageInfo,
-            'hasNextPage' | 'hasPreviousPage'
-          >
-          edges: Array<
-            { __typename?: 'ImageEdge' } & {
-              node: { __typename?: 'Image' } & Pick<
-                Image,
-                'originalSrc' | 'altText' | 'width' | 'height'
-              >
-            }
-          >
-        }
-      }
+  productByHandle?: Maybe<{ __typename?: 'Product' } & ProductDetailsFragment>
+}
+
+export type GetRelatedProductsQueryVariables = Exact<{
+  productId: Scalars['ID']
+}>
+
+export type GetRelatedProductsQuery = { __typename?: 'QueryRoot' } & {
+  productRecommendations?: Maybe<
+    Array<{ __typename?: 'Product' } & ListProductDetailsFragment>
   >
 }
 
diff --git a/framework/shopify/schema.graphql b/framework/shopify/schema.graphql
index 9c657fe43..d627cddef 100644
--- a/framework/shopify/schema.graphql
+++ b/framework/shopify/schema.graphql
@@ -13,16 +13,6 @@ directive @accessRestricted(
   reason: String = null
 ) on FIELD_DEFINITION | OBJECT
 
-"""
-Contextualize data.
-"""
-directive @inContext(
-  """
-  The country code for context.
-  """
-  country: CountryCode!
-) on QUERY | MUTATION
-
 """
 A version of the API.
 """
@@ -829,7 +819,7 @@ input CheckoutAttributesUpdateInput {
   The required attributes are city, province, and country.
   Full validation of the addresses is still done at complete time.
   """
-  allowPartialAddresses: Boolean
+  allowPartialAddresses: Boolean = false
 }
 
 """
@@ -872,7 +862,7 @@ input CheckoutAttributesUpdateV2Input {
   The required attributes are city, province, and country.
   Full validation of the addresses is still done at complete time.
   """
-  allowPartialAddresses: Boolean
+  allowPartialAddresses: Boolean = false
 }
 
 """
@@ -3391,7 +3381,7 @@ input CreditCardPaymentInput {
   """
   Executes the payment in test mode if possible. Defaults to `false`.
   """
-  test: Boolean
+  test: Boolean = false
 }
 
 """
@@ -3422,7 +3412,7 @@ input CreditCardPaymentInputV2 {
   """
   Executes the payment in test mode if possible. Defaults to `false`.
   """
-  test: Boolean
+  test: Boolean = false
 }
 
 """
@@ -5325,7 +5315,7 @@ Represents information about the metafields associated to the specified resource
 """
 interface HasMetafields {
   """
-  The metafield associated with the resource.
+  Returns a metafield found by namespace and key.
   """
   metafield(
     """
@@ -7648,7 +7638,7 @@ type Product implements Node & HasMetafields {
   ): MediaConnection!
 
   """
-  The metafield associated with the resource.
+  Returns a metafield found by namespace and key.
   """
   metafield(
     """
@@ -8150,7 +8140,7 @@ type ProductVariant implements Node & HasMetafields {
   ): Image
 
   """
-  The metafield associated with the resource.
+  Returns a metafield found by namespace and key.
   """
   metafield(
     """
@@ -9298,7 +9288,7 @@ input TokenizedPaymentInput {
   """
   Executes the payment in test mode if possible. Defaults to `false`.
   """
-  test: Boolean
+  test: Boolean = false
 
   """
   Public Hash Key used for AndroidPay payments only.
@@ -9334,7 +9324,7 @@ input TokenizedPaymentInputV2 {
   """
   Whether to execute the payment in test mode, if possible. Test mode is not supported in production stores. Defaults to `false`.
   """
-  test: Boolean
+  test: Boolean = false
 
   """
   Public Hash Key used for AndroidPay payments only.
@@ -9375,7 +9365,7 @@ input TokenizedPaymentInputV3 {
   """
   Whether to execute the payment in test mode, if possible. Test mode is not supported in production stores. Defaults to `false`.
   """
-  test: Boolean
+  test: Boolean = false
 
   """
   Public Hash Key used for AndroidPay payments only.
diff --git a/framework/shopify/utils/queries/get-all-products-query.ts b/framework/shopify/utils/queries/get-all-products-query.ts
index 179cf9812..dcde5191a 100644
--- a/framework/shopify/utils/queries/get-all-products-query.ts
+++ b/framework/shopify/utils/queries/get-all-products-query.ts
@@ -1,3 +1,32 @@
+export const listProductDetailsFragment = /* GraphQL */ `
+  fragment listProductDetails on Product {
+    id
+    title
+    vendor
+    handle
+    priceRange {
+      minVariantPrice {
+        amount
+        currencyCode
+      }
+    }
+    images(first: 1) {
+      pageInfo {
+        hasNextPage
+        hasPreviousPage
+      }
+      edges {
+        node {
+          originalSrc
+          altText
+          width
+          height
+        }
+      }
+    }
+  }
+`
+
 export const productConnectionFragment = /* GraphQL */ `
   fragment productConnection on ProductConnection {
     pageInfo {
@@ -6,33 +35,11 @@ export const productConnectionFragment = /* GraphQL */ `
     }
     edges {
       node {
-        id
-        title
-        vendor
-        handle
-        priceRange {
-          minVariantPrice {
-            amount
-            currencyCode
-          }
-        }
-        images(first: 1) {
-          pageInfo {
-            hasNextPage
-            hasPreviousPage
-          }
-          edges {
-            node {
-              originalSrc
-              altText
-              width
-              height
-            }
-          }
-        }
+        ...listProductDetails
       }
     }
   }
+  ${listProductDetailsFragment}
 `
 
 const getAllProductsQuery = /* GraphQL */ `
diff --git a/framework/shopify/utils/queries/get-product-query.ts b/framework/shopify/utils/queries/get-product-query.ts
index b2998a40a..f0e3e3619 100644
--- a/framework/shopify/utils/queries/get-product-query.ts
+++ b/framework/shopify/utils/queries/get-product-query.ts
@@ -1,72 +1,79 @@
-const getProductQuery = /* GraphQL */ `
-  query getProductBySlug($slug: String!) {
-    productByHandle(handle: $slug) {
+export const productDetailsFragment = /* GraphQL */ `
+  fragment productDetails on Product {
+    id
+    handle
+    availableForSale
+    title
+    productType
+    vendor
+    description
+    descriptionHtml
+    options {
       id
-      handle
-      availableForSale
-      title
-      productType
-      vendor
-      description
-      descriptionHtml
-      options {
-        id
-        name
-        values
+      name
+      values
+    }
+    priceRange {
+      maxVariantPrice {
+        amount
+        currencyCode
       }
-      priceRange {
-        maxVariantPrice {
-          amount
-          currencyCode
-        }
-        minVariantPrice {
-          amount
-          currencyCode
-        }
+      minVariantPrice {
+        amount
+        currencyCode
       }
-      variants(first: 250) {
-        pageInfo {
-          hasNextPage
-          hasPreviousPage
-        }
-        edges {
-          node {
-            id
-            title
-            sku
-            availableForSale
-            requiresShipping
-            selectedOptions {
-              name
-              value
-            }
-            priceV2 {
-              amount
-              currencyCode
-            }
-            compareAtPriceV2 {
-              amount
-              currencyCode
-            }
+    }
+    variants(first: 250) {
+      pageInfo {
+        hasNextPage
+        hasPreviousPage
+      }
+      edges {
+        node {
+          id
+          title
+          sku
+          availableForSale
+          requiresShipping
+          selectedOptions {
+            name
+            value
+          }
+          priceV2 {
+            amount
+            currencyCode
+          }
+          compareAtPriceV2 {
+            amount
+            currencyCode
           }
         }
       }
-      images(first: 250) {
-        pageInfo {
-          hasNextPage
-          hasPreviousPage
-        }
-        edges {
-          node {
-            originalSrc
-            altText
-            width
-            height
-          }
+    }
+    images(first: 250) {
+      pageInfo {
+        hasNextPage
+        hasPreviousPage
+      }
+      edges {
+        node {
+          originalSrc
+          altText
+          width
+          height
         }
       }
     }
   }
 `
 
+const getProductQuery = /* GraphQL */ `
+  query getProductBySlug($slug: String!) {
+    productByHandle(handle: $slug) {
+      ...productDetails
+    }
+  }
+  ${productDetailsFragment}
+`
+
 export default getProductQuery
diff --git a/framework/shopify/utils/queries/get-related-products-query.ts b/framework/shopify/utils/queries/get-related-products-query.ts
new file mode 100644
index 000000000..0a6363030
--- /dev/null
+++ b/framework/shopify/utils/queries/get-related-products-query.ts
@@ -0,0 +1,11 @@
+import { listProductDetailsFragment } from './get-all-products-query'
+
+const getRelatedProductsQuery = /* GraphQL */ `
+  query getRelatedProducts($productId: ID!) {
+    productRecommendations(productId: $productId) {
+      ...listProductDetails
+    }
+  }
+  ${listProductDetailsFragment}
+`
+export default getRelatedProductsQuery
diff --git a/pages/product/[slug].tsx b/pages/product/[slug].tsx
index bb1ecbee3..71ffaf6ff 100644
--- a/pages/product/[slug].tsx
+++ b/pages/product/[slug].tsx
@@ -28,15 +28,27 @@ export async function getStaticProps({
     config,
     preview,
   })
+
   const { pages } = await pagesPromise
   const { categories } = await siteInfoPromise
   const { product } = await productPromise
-  const { products: relatedProducts } = await allProductsPromise
 
   if (!product) {
     throw new Error(`Product with slug '${params!.slug}' not found`)
   }
 
+  const relatedProductsPromise = commerce.getRelatedProducts({
+    variables: { productId: product.id, first: 4 },
+    config,
+    preview,
+  })
+
+  // Temporary conditional query
+  const { products: relatedProducts } =
+    process.env.COMMERCE_PROVIDER === 'shopify'
+      ? await relatedProductsPromise
+      : await allProductsPromise
+
   return {
     props: {
       pages,