前々回では「Shopifyとは何なのか?」「メリット・デメリットは?」「できること・できないことは?」など、Shopifyの概要をお話しして、前回はもう少し技術的なところに踏み込んで「基幹システムとの連携」を観点に、ShopifyのAPIについて説明しました。
今回も引き続きAPIについてのお話なのですが、前回のREST APIとはまた少し違うGraphQL APIを紹介します。
■ShopifyのGraphQL APIとは?
Graph QL とは、Shopifyのデータをクエリで取得できるAPIです。
Shopifyから商品情報、注文情報、顧客情報など、どのようなデータを取得・更新できるのかについては前回のREST APIでも触れましたが、GraphQL APIはREST APIよりも少ないリクエスト回数で、必要なデータを取得することができます。
Shopify GraphQL APIの公式ドキュメント:
https://shopify.dev/docs/api/admin-graphql
REST APIと比べると普及率はまだまだ低いので、そもそもGraphQLとは何なのかを説明します。
GraphQLはAPIの新しいプロトコルで、データベースからデータを取得するためのクエリ言語です。
REST APIとは異なり、必要なデータ項目だけを指定して取得できます。
これを踏まえてShopify REST APIとShopify GraphQL APIとの違いを以下に挙げます。
■Shopify GraphQL APIの概要
クエリを1つ書けばさまざまなデータを取得・更新できるので、REST APIのように「注文情報はOrdersのAPIを呼び出して、発送情報はProductsのAPIを呼び出して、……」と、データごとに呼び出すAPIを分ける必要はありません。
Shopify GraphQL APIのエンドポイントは以下の形式なのですが、
https://{SHOPIFY_DOMAIN}/admin/api/2022-02/graphql.json ({SHOPIFY_DOMAIN}は、Shopifyストアのドメイン名)
REST APIと違って「2022-02/」の後ろに「Orders」や「Customers」などをくっ付けて、呼び出すAPIの指定は不要です。この固定のエンドポイント1つだけで事足ります。
(ただし、2022-02 はAPIのバージョンなので、2023-07 や 2023-10 にどんどん変わっていきます)
そして、使用するHTTPメソッドも以下の1つだけです。
- POST : クエリ (データの取得/作成/更新/削除) を送信する
エンドポイントも1つ、HTTPメソッドも1つ、ではどうやって「どのデータを取得するのか」「データをどうする(取得/更新する)のか」を指定するのでしょうか。
ここで、先ほどから触れている「クエリ」の登場です。
リクエストボディに「このデータをこうしたい」とクエリを書いてGraphQL APIを呼び出すわけです。
もちろん、クエリにはデータの条件なども書けるので「今日入った注文を全件取得」、「注文番号999の支払い情報だけ取得」などといった操作も可能です。
セキュリティ面にも言及しておきますと、APIキー、ロールベースのアクセス制御、暗号化(SSL)などはShopify REST APIと同様ですので前回の記事をご参照下さい。
■Shopify GraphQL APIの使い方
では、実際にAPIを実行してみましょう。
クエリ送信のURLは以下の通りです。 https://storedomain.myshopify.com/admin/api/2023-07/graphql.json
以下の条件で発送データを取得するクエリをリクエストボディに書きます。
- 数回に分割して発送された注文番号「5328720593121」の、全ての発送情報を取得する
- 送り状の情報(trackingInfo)、発送された商品の情報(fulfillmentLineItems)、発送ステータス(status)などを取得する
クエリ:
{ order(id: "gid://shopify/Order/5328720593121") { fulfillmentOrders(first: 5, reverse:true) { edges { node { id status fulfillAt fulfillments(first: 1) { edges { node { trackingInfo { company number } fulfillmentLineItems(first: 10) { edges { node { quantity lineItem { title quantity originalUnitPriceSet { shopMoney { amount currencyCode } } taxLines(first: 5) { rate } discountAllocations { allocatedAmount { amount currencyCode } } } } } } } } } } } } } }
リクエストヘッダにAPIキーを設定し、リクエストをPOST送信すると、JSON形式で以下のようなレスポンスが返ってきます。
{ "data": { "order": { "fulfillmentOrders": { "edges": [ { "node": { "id": "gid:\/\/shopify\/FulfillmentOrder\/6386604474593", "status": "CLOSED", "fulfillAt": "2023-10-02T04:00:00Z", "fulfillments": { "edges": [ { "node": { "trackingInfo": [ { "company": "Fedex", "number": "1231275" } ], "fulfillmentLineItems": { "edges": [ { "node": { "quantity": 1, "lineItem": { "title": "アロマオイル (ピーチ)", "quantity": 1, "originalUnitPriceSet": { "shopMoney": { "amount": "1100.0", "currencyCode": "JPY" } }, "taxLines": [ { "rate": 0.1 } ], "discountAllocations": [] } } }, { "node": { "quantity": 1, "lineItem": { "title": "アロマオイル (バニラ)", "quantity": 1, "originalUnitPriceSet": { "shopMoney": { "amount": "1000.0", "currencyCode": "JPY" } }, "taxLines": [ { "rate": 0.1 } ], "discountAllocations": [] } } } ] } } } ] } } }, { "node": { "id": "gid:\/\/shopify\/FulfillmentOrder\/6382008107233", "status": "CLOSED", "fulfillAt": "2023-09-27T10:00:00Z", "fulfillments": { "edges": [ { "node": { "trackingInfo": [ { "company": "Fedex", "number": "1231273" } ], "fulfillmentLineItems": { "edges": [ { "node": { "quantity": 1, "lineItem": { "title": "マイクロファイバー バスタオル", "quantity": 1, "originalUnitPriceSet": { "shopMoney": { "amount": "1200.0", "currencyCode": "JPY" } }, "taxLines": [ { "rate": 0.1 } ], "discountAllocations": [] } } } ] } } } ] } } }, { "node": { "id": "gid:\/\/shopify\/FulfillmentOrder\/6382007091425", "status": "CLOSED", "fulfillAt": "2023-09-27T10:00:00Z", "fulfillments": { "edges": [] } } } ] } } }, "extensions": { "cost": { "requestedQueryCost": 288, "actualQueryCost": 35, "throttleStatus": { "maximumAvailable": 1000.0, "currentlyAvailable": 965, "restoreRate": 50.0 } } } }
クエリで指定した通りの項目のみ、きちんと返ってきています。
ただ、末尾の項目「extensions」はクエリで指定しなくても必ず付いてきます。
これはクエリ実行にかかったコストの情報です。コストは、クエリの複雑さや取得するデータ量によって変わってくるのですが、この値が大きくなるとエラーが発生します。
コストエラーが発生した時はどうなるのか見てみましょう。
先ほどのクエリにて「first: 5」や「first: 10」を指定しましたが、これは「1つの注文で5回超の分割発送なんてないだろう」「1回の発送に10商品超の梱包なんてないだろう」という業務仕様から決めた値なのですが、この数値を大きくすると、以下のレスポンスが返ってきました。
{ "errors": [ { "message": "Query cost is 2853, which exceeds the single query max cost limit (1000).\n\nSee https://shopify.dev/concepts/about-apis/rate-limits for more information on how the\ncost of a query is calculated.\n\nTo query larger amounts of data with fewer limits, bulk operations should be used instead.\nSee https://shopify.dev/api/usage/bulk-operations/queries for usage details.\n", "extensions": { "code": "MAX_COST_EXCEEDED", "cost": 2853, "maxCost": 1000, "documentation": "https://shopify.dev/api/usage/rate-limits" } } ] }
REST APIと違って、このようなエラーが発生してもHTTPステータスコードは200(成功)です。
ステータスコードではなく、エラーメッセージを確認しないとエラー検出ができないので要注意です。
■Shopify GraphQL APIを使った実例
Shopify REST APIでできることと、ほとんど同じなのですが比較しつつ実例をご紹介します。
- 管理画面上のタイムラインのデータを取得する
商品を発送した、支払い金額の一部を返金した、など注文に対してどんな動きがあったかを把握できます。
タイムラインのデータはGraphQL APIでしか取得できません。
このように、REST APIでは取得できないデータが他にも結構あることを知り、私はGraphQL推しになりました。Shopifyサイドも今後はGraphQL APIのアップデートに力を入れていくのではないでしょうか。
弊社で携わったプロジェクトでもREST APIからGraphQL APIへ移行していきましょう、という動きがありました。
そこで、当該プロジェクトでも積極的にGraphQLを実装に採用したものの、支払い金額関連のデータでGraphQL API では取得できないデータ項目があることに気付きました。
そんな時は、そのデータ項目のみREST API で取得するなどしてGraphQL APIとREST APIの併用で解決しましょう。
個人的には、せっかくGraphQL推しになったのに……と実に無念でしたが。
GraphQL に慣れないうちはクエリを書くのが難しいと感じてしまいますが、ShopifyにはGraphQLエディタが用意されています。
Shopify Admin API GraphiQL explorer https://shopify.dev/docs/apps/tools/graphiql-admin-api
これを使ってクエリを作成すれば、どんなデータ項目があるのか候補を表示してくれますし、もちろんクエリの実行もできてエラーも検出してくれます。
クエリを書いているうちに、
- このデータ項目を取得するにはこのスキーマへのコネクションを使えばいいのか〜 (=データベースのテーブル結合のようなもの)
- このスキーマを実装してるからあのスキーマと類似してるんだな〜 (=JavaやC#のインターフェースをimplementsするようなもの)
という理解が深まり、REST API でShopifyに入門した頃、湧き上がった疑問「どんなデータ構造になっているんだ……。」が解明されていきました。
GraphQLから入った方が分かりやすかったかもしれない……。
■まとめ
ShopifyのGraphQL APIは、Shopifyのデータを効率的に取得するためのAPIです。
Shopify REST APIよりも少ないリクエスト回数で、必要なデータを取得することができます。
もちろん、REST API でも大抵のことはできるのですが、どうせならShopify GraphQL APIをメインで使用して、Shopifyのデータをフル活用してみてはいかがでしょうか。
とは言え、GraphQL APIはREST APIよりも複雑なため、使いこなすにはある程度の知識が必要です。
Shopify GraphQL APIの公式ドキュメントを参照したり、ShopifyのGraphQL エディタを使って徐々に慣れていきましょう。
以上、3回にわたってShopifyに関する記事をお届けしました。
弊社が担当したShopifyの案件では日本とベトナムで開発作業を分担し、ベトナム側ではまずShopify APIの項目を根気よく調査、時にはREST APIを使うべきかGraphQLを使うべきかを考察、次にコーディング、そして結合テストでは画面操作に伴うデータの変化を検証しました。
今後、Shopify関連のオフショア開発案件でそのノウハウを余すことなく活かし、日本とベトナムの両側からお力添え致しますのでShopifyの店舗開設・移行をご検討でしたら是非ご依頼下さい! Xin cảm ơn!!
記事: A.K