loyalty-points-system について
顧客ロイヤルティプログラムを設計する加盟店向けのスキルです。ポイントの獲得・交換、ティア、プラットフォーム別ツールに加え、カスタムまたはヘッドレスストア向けの台帳方式も説明します。
主な機能
- 01ポイント獲得・交換ルール
- 02ティア特典と昇格
- 03プラットフォーム別ロイヤルティアプリ
- 04台帳方式のカスタムシステム設計
- 05残高・有効期限・返金処理
活用シーン
- 01購入・レビュー・紹介への特典付与
- 02配送やポイント特典付き VIP ティアの提供
- 03モバイルアプリでの残高表示と交換
- 04ヘッドレスストアのポイント追跡機能構築
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill loyalty-points-systemインストール後、Claude Code で/loyalty-points-systemを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
tile.jsonevals/ledger-schema-design/criteria.jsontask.mdevals/points-earning-and-tier-progression/criteria.jsontask.mdevals/redemption-checkout-and-expiration-job/criteria.jsontask.md詳細
ロイヤルティポイントシステム
概要
ロイヤルティポイントプログラムでは、購入やその他のアクション(レビュー、紹介、SNS でのシェア)で獲得したポイントを、リピーターに付与します。顧客はポイントをチェックアウト時の割引に利用できます。よく設計されたプログラムでは、顧客の利用額が増えるにつれて、送料無料やポイント倍率のアップなどの特典が受けられるティア(ブロンズ → シルバー → ゴールド → プラチナ)を用意します。ほとんどのマーチャントは、一から構築するのではなく、専用のロイヤルティアプリから始めるべきです。主要なプラットフォームには優れた選択肢が用意されています。
このスキルを使用する場面
- リピート購入率を高めるため、顧客維持の仕組みを追加するとき
- 高額利用の顧客が送料無料や先行アクセスなどの特典を受けられる、ティア制の VIP プログラムを開始するとき
- 顧客が利用状況を確認できる、体系的なロイヤルティプログラムに、その場しのぎの割引システムを置き換えるとき
- 顧客がポイント残高を確認し、チェックアウト時に利用できるモバイルアプリに、ポイントを連携するとき
- 特定のアクション(レビュー、紹介、初回購入)に対してボーナスポイントを付与するキャンペーンを実施するとき
基本手順
ステップ 1:マーチャントのプラットフォームを確認し、適切なツールを選ぶ
| プラットフォーム | 推奨ツール | 理由 |
|---|---|---|
| Shopify | Smile.io(旧 Sweet Tooth)または LoyaltyLion | どちらも Shopify とネイティブに連携し、チェックアウト時のポイント獲得・利用に対応しているほか、ティア管理や紹介プログラムも備えています |
| Shopify(低予算) | Rivo Loyalty & Rewards または Bon Loyalty | 基本的なポイント機能とティア機能を備えた、より低価格の選択肢です |
| WooCommerce | WooCommerce Points and Rewards(公式、約 $79/年)または YITH WooCommerce Points & Rewards | WooCommerce ネイティブの連携に対応しており、公式プラグインは適切に保守されています |
| BigCommerce | Smile.io または LoyaltyLion | どちらも BigCommerce と連携できます |
| マルチプラットフォーム/ヘッドレス | Loyaltylion API、Smile.io API、または Yotpo Loyalty | いずれもカスタムストアフロントとの連携用 API を提供しています |
| カスタム/ヘッドレス | 台帳ベースのポイント管理を構築 | アプリの機能が特定の要件を満たせない場合に限ります |
ステップ 2:ロイヤルティプログラムを設定する
Shopify
Smile.io を使用する(Shopify で最も人気のあるロイヤルティアプリ):
- Shopify App Store から Smile: Loyalty & Rewards をインストールします(無料プランあり。有料プランは月額約 $49 から)。
- Smile のダッシュボードで、ポイント獲得方法を設定します。
- 購入時のポイント(例:利用額 $1 ごとに 1 ポイント)
- アカウント作成、誕生日、商品レビューに対するボーナスポイント
- 友人を紹介したときの紹介ポイント
- ポイントの利用方法を設定します。
- 割引コードとの交換(例:100 ポイントで $1 割引)
- 利用に必要な最低ポイント数を設定
- 1 回の注文で利用できる上限を設定(例:注文額の最大 50%をポイントで利用可能)
- ティアを設定します(VIP プログラム。有料プランで利用可能)。
- ティアの基準を定義します(例:ブロンズ:利用額 $0~$500、シルバー:$500~$1,000、ゴールド:$1,000 以上)
- ティアの特典を設定します:ポイント倍率、限定商品、送料無料
- 顧客向けウィジェットを設定します。ポイントのフローティングウィジェットはストアフロントに自動で表示されます。色や配置をカスタマイズできます。
連携のテスト:
- テスト用の顧客アカウントを作成してテスト注文を行い、注文ステータスが「フルフィルメント済み」に変わった後にポイントが付与されることを確認します。
- チェックアウト時にポイントの利用を試し、割引が正しく適用されることを確認します。
WooCommerce
WooCommerce Points and Rewards の使用方法:
- WooCommerce.com から WooCommerce Points and Rewards をインストールします
- WooCommerce → Points and Rewards → Settings に移動します:
- Earn points:ポイント付与率を設定します(例:1ドルの購入につき1ポイント)
- Earn points for:購入、レビュー、アカウント登録を対象に設定します
- Redeem points:ポイント交換率を設定します(例:100ポイントで1ドルの割引)
- Maximum discount:注文ごとに交換できる割引額の上限を設定します
- Points expire:必要に応じて有効期限を設定します
- WooCommerce → Points and Rewards → Manage Points で顧客ごとの残高を管理します
- 顧客のアカウントページにポイントが自動的に表示されます
WooCommerce での会員ランクについて: 公式プラグインには会員ランク管理機能が含まれていません。次の方法があります:
- YITH WooCommerce Points & Rewards:会員ランク/VIP 機能を備えています
- Gamification for WooCommerce:会員ランクと実績バッジを追加します
- 累計購入額に基づいて WooCommerce の顧客グループ(ロール)を手動で割り当て、グループごとに価格や送料を設定します
BigCommerce
BigCommerce での Smile.io の使用方法:
- BigCommerce App Marketplace から Smile.io をインストールします
- 上記の Shopify のセクションと同じ手順で Smile.io を設定します。インターフェースはほぼ同じです
- Smile.io は BigCommerce のチェックアウトと連携し、クーポンコードとしてロイヤルティ割引を適用します
LoyaltyLion の使用方法:
- BigCommerce App Marketplace から LoyaltyLion をインストールします
- LoyaltyLion ダッシュボードでポイント付与ルールと交換方法を設定します
- アプリはアカウントページに顧客向けロイヤルティパネルを追加し、BigCommerce のチェックアウトと連携します
カスタム/ヘッドレス
ヘッドレスのストアフロントを構築する場合や、アプリの機能では不十分な場合は、台帳ベースのポイントシステムを構築します。台帳パターン(追記専用の取引記録、残高カラムなし)を採用すると、正確性が保たれ、完全な監査証跡が得られ、ポイントの取り消しも簡単になります。
CREATE TABLE loyalty_accounts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
customer_id UUID NOT NULL UNIQUE,
tier VARCHAR(16) NOT NULL DEFAULT 'bronze',
lifetime_spend_cents INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE loyalty_ledger (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
account_id UUID NOT NULL REFERENCES loyalty_accounts(id),
points INTEGER NOT NULL, -- positive = earned, negative = redeemed/expired
type VARCHAR(32) NOT NULL CHECK (type IN ('purchase', 'bonus', 'referral', 'redemption', 'expiration', 'adjustment')),
reference_id UUID, -- order_id, review_id, etc.
description TEXT NOT NULL,
expires_at TIMESTAMPTZ, -- NULL = never expires
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
期限切れの取引を除いたポイント残高:
async function getPointsBalance(accountId: string): Promise<number> {
const result = await db.raw(`
SELECT COALESCE(SUM(points), 0) AS balance
FROM loyalty_ledger
WHERE account_id = ?
AND (expires_at IS NULL OR expires_at > NOW())
`, [accountId]);
return Math.max(0, parseInt(result.rows[0].balance, 10));
}
注文のフルフィルメント後にポイントを付与する(購入時ではなく付与することで、返品によるポイントの不正取得を防ぎます):
const TIER_MULTIPLIERS = { bronze: 1, silver: 1.25, gold: 1.5, platinum: 2 };
const POINTS_PER_DOLLAR = 1;
const EXPIRY_MONTHS = 12;
async function awardPurchasePoints(customerId: string, orderId: string, subtotalCents: number) {
const account = await getOrCreateAccount(customerId);
const multiplier = TIER_MULTIPLIERS[account.tier];
const points = Math.round((subtotalCents / 100) * POINTS_PER_DOLLAR * multiplier);
const expiresAt = new Date();
expiresAt.setMonth(expiresAt.getMonth() + EXPIRY_MONTHS);
await db.loyaltyLedger.insert({
account_id: account.id, points, type: 'purchase',
reference_id: orderId, description: `Points for order ${orderId}`, expires_at: expiresAt,
});
// Update lifetime spend and recalculate tier
await db.loyaltyAccounts.update(account.id, {
lifetime_spend_cents: account.lifetime_spend_cents + subtotalCents,
});
await recalculateTier(account.id);
}
チェックアウト時にポイントを交換する:
const REDEMPTION_RATE = 0.01; // 100 points = $1
async function redeemPoints(customerId: string, orderId: string, pointsToRedeem: number): Promise<{ discountCents: number }> {
const account = await db.loyaltyAccounts.findByCustomerId(customerId);
const balance = await getPointsBalance(account.id);
if (pointsToRedeem > balance) throw new Error('Insufficient points');
const discountCents = Math.floor(pointsToRedeem * REDEMPTION_RATE * 100);
await db.loyaltyLedger.insert({
account_id: account.id, points: -pointsToRedeem, type: 'redemption',
reference_id: orderId, description: `Redeemed for order ${orderId}`,
});
return { discountCents };
}
ベストプラクティス
- 購入時ではなく、フルフィルメント後にポイントを付与する — 返品予定の注文で顧客がポイントを獲得するのを防ぎます。ほとんどのロイヤルティアプリには、設定可能な「保留期間」があります
- UI ではポイントを金額で表示する — 「500ポイントあります」よりも「報酬として5.00ドル分あります」のほうが購入につながります。金額を目立つように表示します
- ポイントの有効期限を知らせるメールを送信する — 有効期限の30日前に顧客へメールを送信します。これは購入を促すとともに、再エンゲージメントにつながる効果が実証されたきっかけです
- 注文ごとの交換上限を設ける — 利益率を守るため、注文金額の最大50%までをポイントで交換できるようにします
- 注文が返金されたらポイントを取り消す — 返金イベントに関連付けたマイナス調整の取引を追加します。手作業での修正に頼らないでください
- 次の会員ランクまでの必要額を表示する — 「あと47ドルの購入でゴールドに到達」のような表示は、現在の会員ランクだけを表示するよりも追加購入を促します
- シンプルに始める — 会員ランクを追加する前に、固定のポイント付与率で開始します。会員ランクは複雑さとカスタマーサービスの負担を増やすため、まずプログラムの効果を確認します
よくある落とし穴
| 問題 | 解決策 |
|---|---|
| 返品された注文に対して顧客にポイントが付与される | 返品期間が終了してからポイントを付与するか、返品処理時にポイントを取り消します |
| ランクの降格が顧客を混乱させる | 注文ごとではなく、事前に定めた日付(年次など)にのみランクの降格を判定し、ポリシーを明確に伝えます |
| 紹介の不正 — 顧客が自分自身を紹介する | 紹介者と被紹介者のメールアドレスや請求先住所が異なることを確認して、紹介を検証します |
| プラットフォームの更新後、アプリがポイントを付与しなくなる | ロイヤルティアプリの監視アラートを設定し、自動テスト注文を使って毎週ポイント付与をテストします |
| 同期の遅延により、チェックアウト時にポイント残高がゼロと表示される | カスタム構築の場合は台帳からリアルタイムで残高を計算します。アプリベースのプログラムの場合は、アプリがチェックアウトと完全に連携していることを確認します |
関連スキル
- @coupon-management
- @gift-cards
- @ab-testing-pricing
- @customer-segmentation
- @discount-engine