
Shopifyのカスタマーアカウント関連機能には、様々な拡張手段が提供されています。先述のInline extensionsでは、主にUI表示のカスタマイズが中心でした。しかし、顧客情報や注文情報をより有効活用するためには、UIの表示だけではなく、実際のアクション(操作)を伴う拡張が必要になるケースがあります。そこで登場するのがOrder action extensionsです。これを使うことで、注文履歴や注文詳細などのページに独自のアクションを追加でき、より幅広い機能を顧客アカウントに組み込むことが可能になります。
以下では、Order action extensionsの概要からユースケース、導入手順までを解説し、活用におけるポイントを整理します。
Order action extensionsとは?
Order action extensionsは、その名のとおり「顧客の注文に対して追加のアクションをトリガーできる拡張機能」です。具体的には、注文一覧や注文詳細ページなどにカスタムボタンやリンクを配置し、そこから外部APIを呼び出したり、別の画面に遷移させたりといった流れを作り出せます。これにより、Shopifyの標準機能だけでは実現しにくかったさまざまな操作フローをユーザーに提供できるようになります。
Shopifyが提供する従来の拡張では、UI上への情報表示は比較的自由度が高いものの、操作の流れや特定のアクションを加えることは制限が多い部分でした。Order action extensionsはその制限を補完し、顧客自身がよりインタラクティブな操作を行える仕組みを追加します。
代表的なユースケース
- 交換リクエスト
顧客が注文の詳細画面から「交換依頼」をボタン1つで行えるフローを実装できます。
たとえば、交換フォームを外部サービスで管理している場合でも、Order action extensionsを利用してShopify管理画面からワンクリックでフォームに移動させるなど、スムーズな連携が可能です。 - 追加料金やキャンセル処理の申請
注文に加えたいオプションサービスの料金を別途徴収したい場合、追加料金の請求フローを開始するボタンを表示できます。
逆に、キャンセル申請を自動処理するためのフローを提供することも考えられます。顧客アカウント画面で解決できるため、サポートコストの削減にもつながります。 - カスタム配送依頼や日時指定
既存の配送設定だけでは対応しきれない特別な配送方法や日時指定を受け付けるボタンを配置し、外部の配送管理サービスと連携することが可能になります。
特に多言語多通貨対応や海外配送のカスタム処理を行いたい場合に便利です。 - 再購入・定期購入へのアップセル
定期購入を促すために、「定期便に切り替える」といったボタンを配置し、そこからShopifyのサブスクリプション機能や外部アプリを呼び出すフローを作るのも効果的です。顧客が購入履歴を見たタイミングでダイレクトに提案できるため、売上の向上が期待できます。
Inline extensionsとの違い
Inline extensionsは主にUIの“見た目”部分(バナーやメッセージ、リンク表示など)を柔軟に追加する機能でした。一方、Order action extensionsは顧客による「操作」を扱うため、どのようなアクションを提供するかが重要となります。
たとえばInline extensionsの場合、あくまでもデータの表示をカスタマイズしてUXを向上させることが主な目的であり、顧客が押すボタンやクリックしたリンク先は「Shopifyの標準フローの延長」に留まります。
しかし、Order action extensionsならクリック後に外部サービスのAPIを叩く、別ドメインに移動させる、あるいは内部で複雑なロジックを実行するなどが可能です。実際のところは、バックエンドとの連携方法次第で実現できる範囲が広がるため、企業ごとの運用フローやカスタマイズ要件に応じて構成を決めることが大切です。
実装手順の紹介
今回は注文一覧画面から商品に問題があったことを報告するボタンを追加するケースを例に、Order action extensionsの実装手順を紹介します。
extensionの作成
まずは、拡張機能を作成します。以下のコードを実行します。
shopify app generate extension --template=customer_account_ui --name=action-menu-extension-react --flavor=typescript-react
action-menu-extension-reactという名前のCustomer Account UI extensionが作成されます。ここではTypeScriptベースのReactフレームワークを選択して作成しています。
ターゲットの設定
どこにUIを出すのかを設定します。作成したextensionディレクトリにあるshopify.extension.tomlを開き、以下のように設定します。
[[extensions]]
type = "ui_extension"
name = "action-menu-extension-react"
handle = "action-menu-extension-react"
[[extensions.targeting]]
module = "./src/MenuActionExtension.tsx"
target = "customer-account.order.action.menu-item.render"
[[extensions.targeting]]
module = "./src/MenuActionModalExtension.tsx"
target = "customer-account.order.action.render"
customer-account.order.action.menu-item.renderは、注文一覧画面のメニューにボタンを追加するターゲットです。一方、customer-account.order.action.renderは、ボタンを押した際に表示されるモーダル画面のターゲットです。
UIの作成
注文アクションメニュー項目を作成します。
src/MenuActionExtension.tsxを開き、以下のように記述します。
import {
Button,
reactExtension,
} from "@shopify/ui-extensions-react/customer-account";
export default reactExtension(
"customer-account.order.action.menu-item.render",
async (api) => {
// https://shopify.dev/docs/api/customer-account-ui-extensions/unstable/targets/order-action-menu/customer-account-order-action-menu-item-render > orderId
const { orderId } = api;
let hasFulfillments = false;
try {
const orderQuery = {
query: `query {
order(id: "${orderId}") {
fulfillments(first: 1) {
nodes {
latestShipmentStatus
}
}
}
}`,
};
const result = await fetch(
"shopify://customer-account/api/2024-10/graphql.json",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(orderQuery),
},
);
const { data } = await result.json();
hasFulfillments = data.order && data.order.fulfillments.nodes.length > 0;
} catch (error) {
console.log(error);
hasFulfillments = false;
}
return <MenuActionExtension showAction={hasFulfillments} />;
},
);
function MenuActionExtension({ showAction }: { showAction: boolean }) {
if (!showAction) {
return null;
}
return <Button>問題を報告する</Button>;
}
このコードではCustomer Account APIを使って注文情報を取得し、注文に紐づく配送情報があるかどうかを判定しています。配送情報がある場合には「問題を報告する」というボタンを表示します。
モーダル画面の作成
ボタンを押した際に表示されるモーダル画面を作成します。
src/MenuActionModalExtension.tsxを開き、以下のように記述します。
import {
Button,
CustomerAccountAction,
reactExtension,
useApi,
Select,
Form,
} from "@shopify/ui-extensions-react/customer-account";
import { useState } from "react";
export default reactExtension("customer-account.order.action.render", () => (
<MenuActionModalExtension />
));
const dtcOptions = [
{ value: "1", label: "パッケージに傷があった" },
{ value: "2", label: "部品が欠けていた" },
{ value: "3", label: "間違った商品が届いた" },
{ value: "4", label: "商品が届くのが遅かった" },
{ value: "5", label: "いまだに商品が届いていない" },
];
const b2bOptions = dtcOptions.concat([
{ value: "6", label: "間違った会社の配送先に届いた" },
]);
function MenuActionModalExtension() {
const { close, authenticatedAccount } =
useApi<"customer-account.order.action.render">();
const [currentProblem, setCurrentProblem] = useState("1");
const [isLoading, setIsLoading] = useState(false);
const isB2BCustomer = authenticatedAccount.purchasingCompany.current != null;
function onSubmit() {
// 問題報告を保存するためにサーバーにリクエストすることをシミュレート
setIsLoading(true);
setTimeout(() => {
setIsLoading(false);
close();
}, 750);
}
return (
<CustomerAccountAction
title="問題を報告する"
primaryAction={
<Button loading={isLoading} onPress={() => onSubmit()}>
送信
</Button>
}
secondaryAction={
<Button
onPress={() => {
close();
}}
>
キャンセル
</Button>
}
>
<Form onSubmit={() => onSubmit()}>
<Select
label="問題を選択"
options={isB2BCustomer ? b2bOptions : dtcOptions}
value={currentProblem}
onChange={(value) => setCurrentProblem(value)}
/>
</Form>
</CustomerAccountAction>
);
}
このコードでは、問題報告の内容を選択するセレクトボックスを表示し、送信ボタンを押すと問題報告をサーバーに送信する処理を行います。b2bの顧客の場合は、dtcOptionsに加えてb2bOptionsを表示して、b2bの顧客に対応した選択肢を提供しています。
アクセススコープの設定
Customer Account APIを使うためには、アクセススコープを設定する必要があります。
今回は注文情報を参照しているのでcustomer_read_orders
を追加します。その他のスコープについては、[Customer access scopes]を参照してください。
アプリのルートにあるshopify.app.toml
を開き、スコープを以下のように設定します。
[access_scopes]
scopes = "customer_read_orders"
インストール
拡張機能をShopifyにデプロイします。以下のコマンドを実行します。
shopify app deploy
デプロイ後、ストアにインストールしてください。
動作確認
extensionを起動して動作確認を行います。以下のコマンドを実行します。
shopify app dev
コンソールにPreview URLが表示されるので、ブラウザでアクセスして動作を確認します。
Developer Consoleが表示されるので作成したaction-menu-extension-reactのPreview linkをクリックします。
問題を報告するボタンが表示されているのがわかりますね。ボタンを押すと問題報告画面が表示されます。
サンプルでは問題報告を送信するとモーダルが閉じるようになっています。問題報告の内容をサーバーに送信する処理を追加することで、問題報告を実際に送信できるようになります。
運用・実装上のポイント
- 権限管理
追加注文など機密性の高いフローを取り扱う場合、顧客アカウントの状態や注文ステータスをしっかり確認してからアクションを実行する必要があります。注文状態が特定のステータス以外のときにはボタンを非活性化しておくなど、操作ミスを防ぐ工夫が欠かせません。 - レスポンスのハンドリング
ボタンが押された後、外部APIの呼び出し結果やエラーレスポンスを顧客にどう通知するかが重要です。例えば、連携先サービスがエラーを返した場合、顧客に適切なエラーメッセージを表示できるようにUIを設計しましょう。 こうしたユーザー体験設計を怠ると、顧客が「何か失敗したっぽいけどよく分からない」という状態に陥りやすくなるため注意が必要です。 - 外部サービス連携時のセキュリティ
顧客情報や注文情報を外部サービスに送信する際には、アクセス制御やデータ保護の観点で十分なセキュリティ対策を行う必要があります。通信はHTTPSで行うのはもちろん、APIキーやトークンの管理をShopify Vaultなどに安全に保管する仕組みを検討しましょう。 - UIの配置場所とガイドラインの遵守
Shopifyの提供するデザインガイドラインに反しないようにしつつ、顧客が使いやすい位置・タイミングでアクションを提示することが大切です。むやみに目立つ場所に多くのボタンを置くとUIが煩雑になり、逆に機能が埋もれてしまう恐れもあります。最適な導線と表示タイミングを考慮して設計しましょう。 - 拡張の順序や組み合わせ
Inline extensionsなどほかの拡張と同時に使う場合は、表示順序やコンポーネント同士の干渉が起きないよう注意が必要です。特に複数のOrder action extensionsを同時に提供する場合、顧客がどの操作を優先すればよいのか分かりにくくなるケースがあります。明確な区分けや説明文を追加して、ユーザーが混乱しないよう配慮しましょう。
Order action extensions導入で得られるメリット
- サポート負荷の軽減
顧客が自分のアカウント画面から直接リクエストを投げられるため、メールや電話での問い合わせ対応を減らせます。顧客にとっても素早く手続きが完結できるため、満足度向上につながります。 - 操作フローの一元化
Shopify上で完結させたいフローを外部サービスへ誘導するだけでなく、Shopify管理画面と顧客アカウント双方で状況をリアルタイムに把握できるようになり、オペレーションの一元管理がしやすくなります。 - 新たなビジネスモデルへの拡張
定期購入や追加オプションなど、既存の枠を超えたビジネス施策を素早く実装できます。顧客アカウントに付加価値のあるアクションを組み込むことで、リピーターを増やしたり高単価を狙ったりといったマーケティングにも有利です。
まとめ
Order action extensionsは、Shopifyの顧客アカウント体験を一層拡張し、顧客が注文管理において自在に操作を行える環境を整えるための強力な仕組みです。これまでサポート担当者や別サイトに任せていたフローをShopify内で完結できるようになり、顧客・管理者双方の使い勝手を大幅に向上させます。
導入を検討する際には、要件の整理やセキュリティ対策、UI/UXデザインなどに十分配慮しつつ、他のカスタマイズ機能(Inline extensionsやApp proxyなど)との組み合わせを検討するとよいでしょう。 店舗独自のブランド体験や顧客ロイヤルティの醸成を強化するうえでも、Order action extensionsは欠かせないツールになり得ます。ぜひ活用を検討してみてください!