これまで、Shopify JavaScript Buy SDKを使ってShopifyのカート操作やチェックアウトを実装していたのですが、2025年1月に廃止になってしまいました。
Deprecation notice
Note: The JS Buy SDK is deprecated as of January, 2025. It will no longer be updated or maintained by Shopify past that point. A final major version will be released in January 2025 to remove the SDK's dependency on the deprecated Checkout APIs, replacing them with Cart APIs. Updating to this new version will allow the SDK to continue to function for most use cases.
If you are using the JS Buy SDK, you have two options:
1. Recommended Option: switch to the Storefront API Client
The Storefront API Client manages the API's authentication information and provides various methods that enable devs to interact with the API. This is the preferred and more future-proof solution. See this migration guide to help you transition.
2. Stopgap Option: Upgrade to JS Buy SDK V3 (coming soon)
This allows you to maintain your current setup with minimal changes for use cases that are supported by the Cart API. A migration guide with details on supported use cases will be available soon. If you choose this option, we still recommend that you switch to the Storefront API Client in the future.
Critical Deadline: July 1st, 2025. You must implement one of these changes by this date, or customers will not be able to complete purchases. Please choose the option that best suits your needs and timelines.
https://github.com/Shopify/js-buy-sdk より引用
廃止のお知らせ
注: JS Buy SDK は 2025 年 1 月をもって廃止されます。それ以降は、Shopify による更新やメンテナンスは行われません。最終メジャー バージョンは 2025 年 1 月にリリースされ、廃止された Checkout APIへの SDK の依存関係が削除され、 Cart APIに置き換えられます。この新しいバージョンに更新すると、ほとんどのユース ケースで SDK が引き続き機能するようになります。
JS Buy SDK を使用している場合は、次の 2 つのオプションがあります。
1. 推奨オプション: Storefront APIクライアントに切り替える
Storefront API クライアントは、API の認証情報を管理し、開発者が API と対話できるようにするさまざまな方法を提供します。これは、推奨される、より将来性のあるソリューションです。移行に役立つこの移行ガイドを参照してください。
2. 暫定オプション: JS Buy SDK V3 へのアップグレード (近日公開)
これにより、Cart API でサポートされているユースケースに対して、最小限の変更で現在の設定を維持できます。サポートされているユースケースの詳細が記載された移行ガイドは、近日中に公開される予定です。このオプションを選択した場合でも、将来的には Storefront API クライアントに切り替えることをお勧めします。
重要な期限: 2025 年 7 月 1 日。この日までにこれらの変更のいずれかを実施する必要があります。そうしないと、顧客は購入を完了できなくなります。ニーズとタイムラインに最も適したオプションを選択してください。
Google翻訳にて翻訳
そんなこんなで、Shopify JavaScript Buy SDKで実装していた箇所を、Storefront API Clientで実装し直すことになりました。
shopify-buyからstorefront-api-clientへの移行で行ったことの記録を残しておこうと思います。
チェックアウトの作成
shopify-buy
import Client from 'shopify-buy'; const client = Client.buildClient({ apiVersion: '2024-04', domain: 'your-shop-name.myshopify.com', storefrontAccessToken: 'your-access-token', }); async function createCheckout() { const checkout = await client.checkout.create(); return checkout; }
@shopify/storefront-api-client
import { createStorefrontApiClient } from '@shopify/storefront-api-client'; interface Cart { id: string; checkoutUrl: string; } interface CartCreateResponse { cartCreate: { cart: Cart; }; } async function createCheckout() { const client = createStorefrontApiClient({ apiVersion: '2025-01', storeDomain: 'your-shop-name.myshopify.com', publicAccessToken: 'your-access-token', }); const query = ` mutation { cartCreate { cart { id checkoutUrl } } } `; const { data } = await client.request<CartCreateResponse>(query); return data?.cartCreate.cart; }
カートに商品を追加
shopify-buy
async function addToCheckout({ checkoutId, variantId, quantity }) { const checkout = await client.checkout.addLineItems( checkoutId, [{ variantId, quantity }] ); return checkout; }
@shopify/storefront-api-client
interface CartLine { id: string; quantity: number; merchandise: { id: string; product: { id: string; title: string; images: { edges: [ { node: { src: string; } } ] } } price: { amount: number; }; }; } interface CartLinesAddResponse { cartLinesAdd: { cart: { id: string; checkoutUrl: string; cost: { subtotalAmount: { amount: number; currencyCode: string; } }; lines: { edges: { node: CartLine }[]; }; }; }; } async function addToCheckout({ cartId, merchandiseId, quantity }) { const mutation = ` mutation addCartLines($cartId: ID!, $lines: [CartLineInput!]!) { cartLinesAdd(cartId: $cartId, lines: $lines) { cart { id checkoutUrl cost { subtotalAmount { amount currencyCode } } lines(first: 10) { edges { node { id quantity merchandise { ... on ProductVariant { id product { id title images(first:1) { edges { node { src } } } } price { amount } } } } } } } } } `; const variables = { cartId, lines: [ { merchandiseId, quantity, }, ], }; const { data } = await client.request<CartLinesAddResponse>(mutation, { variables }); return data?.cartLinesAdd.cart; }
カートから商品を削除
shopify-buy
async function removeFromCheckout({ checkoutId, lineItemId }) { const checkout = await client.checkout.removeLineItems( checkoutId, [ lineItemId ] ); return checkout; }
@shopify/storefront-api-client
interface CartLinesRemoveResponse { cartLinesRemove: { cart: { id: string; checkoutUrl: string; cost: { subtotalAmount: { amount: number; currencyCode: string; } }; lines: { edges: { node: CartLine }[]; }; }; }; } interface CartLine { id: string; quantity: number; merchandise: { id: string; product: { id: string; title: string; images: { edges: [ { node: { src: string; } } ] } } price: { amount: number; }; }; } export async function removeFromCheckout({ cartId, lineItemIds }: { cartId: string; lineItemIds: string[]; }) { const mutation = ` mutation removeCartLines($cartId: ID!, $lineItemIds: [ID!]!) { cartLinesRemove(cartId: $cartId, lineIds: $lineItemIds) { cart { id checkoutUrl cost { subtotalAmount { amount currencyCode } } lines(first: 10) { edges { node { id quantity merchandise { ... on ProductVariant { id product { id title images(first:1) { edges { node { src } } } } price { amount } } } } } } } } } `; const variables = { cartId, lineItemIds, }; const { data } = await client.request<CartLinesRemoveResponse>(mutation, { variables }); return data?.cartLinesRemove.cart; }
カートの中にある商品の数を変更
shopify-buy
export async function updateCheckoutQuantity({ checkoutId, id, quantity }: { checkoutId: string; id: string; quantity: number; }) { const checkout = await client.checkout.updateLineItems( checkoutId, [{ id, quantity }] return checkout; }
@shopify/storefront-api-client
interface CartLine { id: string; quantity: number; merchandise: { id: string; product: { id: string; title: string; images: { edges: [ { node: { src: string; } } ] } } price: { amount: number; }; }; } interface CartLinesUpdateResponse { cartLinesUpdate: { cart: { id: string; checkoutUrl: string; cost: { subtotalAmount: { amount: number; currencyCode: string; } }; lines: { edges: { node: CartLine }[]; }; }; }; } async function updateCheckoutQuantity({ cartId, id, quantity }: { cartId: string; id: string; quantity: number; }) { const mutation = ` mutation updateCartLines($cartId: ID!, $lines: [CartLineUpdateInput!]!) { cartLinesUpdate(cartId: $cartId, lines: $lines) { cart { id checkoutUrl cost { subtotalAmount { amount currencyCode } } lines(first: 10) { edges { node { id quantity merchandise { ... on ProductVariant { id product { id title images(first:1) { edges { node { src } } } } price { amount } } } } } } } } } `; const variables = { cartId, lines: [{ id, quantity }], }; const { data } = await client.request<CartLinesUpdateResponse>(mutation, { variables }); return data?.cartLinesUpdate.cart; }
カートの中身を全て取得
@shopify/storefront-api-client
interface CartLine { id: string; quantity: number; merchandise: { id: string; product: { id: string; title: string; images: { edges: [ { node: { src: string; } } ] } } price: { amount: number; }; }; } interface CartLinesResponse { cart: { id: string; checkoutUrl: string; cost: { subtotalAmount: { amount: number; currencyCode: string; } }; lines: { edges: { node: CartLine; cursor: string }[]; pageInfo: { hasNextPage: boolean; }; }; }; } export async function fetchAllCartItems(cartId: string) { let allItems: { node: CartLine }[] = []; let cursor: string | null = null; let hasNextPage = true; let checkoutUrl = ''; let cost: any = {}; while (hasNextPage) { const query = ` query getCartLines($cartId: ID!, $cursor: String) { cart(id: $cartId) { id checkoutUrl cost { subtotalAmount { amount currencyCode } } lines(first: 100, after: $cursor) { edges { node { id quantity merchandise { ... on ProductVariant { id product { id title images(first:1) { edges { node { src } } } } price { amount } } } } cursor } pageInfo { hasNextPage } } } } `; const variables: { cartId: string; cursor: string | null } = { cartId, cursor }; const { data } = await client.request<CartLinesResponse>(query, { variables }); checkoutUrl = data?.cart.checkoutUrl || ''; cost = data?.cart.cost || {}; const lines = data?.cart.lines; if (lines) { allItems = allItems.concat(lines.edges); hasNextPage = lines.pageInfo.hasNextPage; cursor = hasNextPage ? lines.edges[lines.edges.length - 1].cursor : null; } else { return []; } } return { id: cartId, cost, checkoutUrl, lines: { edges: allItems } }; }
こんな感じで移行しました。