B2B Integration

Follow these steps to integrate Shopify's B2B functionality. If the repo was created before Blueprint version 1.14.0, then the New Customer Account API migration is required before continuing.

Code Migration

The commit links (paired with some steps) direct to a Blueprint PR used only for reference purposes.

Return buyer from root loader

Update the root.tsx loader to fetch and return buyer [commit]


Storefront API buyer query variable for Graphql

Add buyer variable to every Storefront API Graphql query for only product, collection, and search. Do not add to queries for the Pack API [example]

For each query:

  1. Add $buyer: BuyerInput to the variables
  2. Add buyer: $buyer into @inContext()

For example, this product query:

export const PRODUCT_QUERY = `#graphql
  query Product(
    $handle: String!
    $country: CountryCode
    $language: LanguageCode
  ) @inContext(country: $country, language: $language) {
    ...
  }
`;

Becomes:

export const PRODUCT_QUERY = `#graphql
  query Product(
    $handle: String!
    $country: CountryCode
    $language: LanguageCode
    $buyer: BuyerInput
  ) @inContext(country: $country, language: $language, buyer: $buyer) {
    ...
  }
`;

Storefront API buyer query variable for client

Add buyer variable to every storefront client query for product, collection, and search. This does not apply to the pack or admin clients.

  1. In app/lib create a new file called b2b.server.ts [commit]
import type {AppLoadContext} from '@shopify/remix-oxygen';

/* Buyer contextualization for B2B */
export const getBuyerVariables = async (context: AppLoadContext) => {
  const {customerAccount} = context;
  const buyer = await customerAccount.getBuyer();
  return buyer?.companyLocationId && buyer?.customerAccessToken
    ? {
        buyer: {
          companyLocationId: buyer.companyLocationId,
          customerAccessToken: buyer.customerAccessToken,
        },
      }
    : null;
};
  1. Search the codebase for every instance of storefront.query, which will occur in loader or server logic

  2. If the storefront query is related to product, collection or search, the buyer variable needs to be passed in [example]

  • In Blueprint, the routes that had this change were: api.collection, api.predictive-search, api.product-by-id, api.product, api.recommendations, api.search, collections.$handle, products.$handle and search
  • And files products.server.ts and server.utils.ts,

Example:

import {getBuyerVariables} from '~/lib/b2b.server';

...

export async function loader({context, request}: LoaderFunctionArgs) {

...

const buyerVariables = await getBuyerVariables(context);

let {product} = await storefront.query(PRODUCT_QUERY, {
  variables: {
    handle,
    selectedOptions,
    country: storefront.i18n.country,
    language: storefront.i18n.language,
    ...buyerVariables,
  },
  cache: storefront.CacheShort(),
});
  • There is also a change to the props for getFilters in server.utils.ts [commit], which gives way to a change in collections.$handle [commit] and search [commit]

B2B Provider and Components

  1. Add route ($locale).api.b2blocations.tsx to the app/routes folder [commit]
  2. Download this B2B folder and paste folder into the app/components folder
  3. Add <B2BLocationProvider> alongside where all other Provider's wrap the html [commit]
  • The provider also will automatically open B2BLocationSelectorModal if the customer has not yet selected a location. The modal will only close once a location is selected. Changes to Modal are made to accommodate this new logic (instructions in later steps)
  • Depending on the Blueprint version, openModal in B2BLocationProvider and closeModal in B2BLocationSelectorModal will come from either useMenu or useGlobal. If it's from useGlobal, correct accordingly
  1. Add <B2BQuantityRules /> and <B2BPriceBreaks /> under the PDP AddToCart [commit]
  • These display the quantity rules and price breaks, respectively for the selected variant
  1. Add <B2BLocation /> to the customer account menu [commit]
  • This displays the customer's location and a button to open the B2BLocationSelectorModal to switch location
  • openModal from useMenu will also need to be corrected if comes from useGlobal

Add quantityRule and quantityPriceBreaks fields

  1. Add quantityRule and quantityPriceBreaks to VARIANT_FRAGMENT [commit]
  2. Add quantityRule and quantityPriceBreaks inside merchandise in CART_LINE_FRAGMENT and CART_LINE_COMPONENT_FRAGMENT [commit]

Add quantityRule logic for quantity and quantity selectors

Apply the increment, minimum and maximum settings to all quantity and quantity selectors

  1. Change default PDP quantity from 1 to the increment value [commit]
  2. Add quantityRule logic for the PDP QuantitySelector [commit]
  3. Add quantityRule logic for the useCartLine hook [commit]
  4. Pass disableDecrement and disableIncrement to the cart line QuantitySelector [commit]
  5. Wherever else there is a default product quantity, e.g. quick shop, apply the same change from step 1
  6. Wherever else QuantitySelector is used, apply the same logic from step 2 or 3

Customer types

  1. Add customer.types.ts to the app/lib/types folder [commit]
  2. Add its export to the index.ts file [commit]

Add disableClose prop to Modal

This additional Modal setting is to disable the customer from closing the modal when asked to choose a location, if a location has not yet been selected

  1. In either MenuProvider.tsx or GlobalProvider.tsx (depending on what version Blueprint the store was built on), update defaultModal and openModal [commit]
  2. In either context.types.ts or global.types.ts, add disableClose type to Modal and update openModal type [commit]
  3. In Modal.tsx, update the onClose attribute for Dialog and wrap the close button in a disableClose conditional [commit]

Update buyerIdentity

Add purchasingCompany field inside buyerIdentity in CART_FRAGMENT [commit]

Was this page helpful?