2026年9月26日

2026年9月26日

WooCommerceに会員ランク(ゴールド・シルバー・ブロンズ)を追加する方法

WooCommerceに「ゴールド・シルバー・ブロンズ」のような会員ランクを付けるには、顧客ごとの購入実績から自動でランクを決めてユーザーメタに保存し、そのランクに応じてカートで割引をかける、という3段構成で作るのが分かりやすい方法です。この記事では、ランクの判定基準の決め方、注文完了時の自動更新、カートでの割引、マイアカウントでの表示までを、子テーマやmu-pluginにそのまま置けるコードで解説します。プラグインで済ませる選択肢も最後に紹介します。

作る前に決めること

コードを書く前に、ランクのルールを文章で決めておきます。ここが曖昧なまま実装すると、返金や期間の扱いで後から問い合わせが増えます。

  • 何で判定するか:累計購入額、直近12か月の購入額、購入回数など。この記事では「直近12か月の完了済み注文の合計額(返金分を差し引く)」を使います。
  • しきい値:例としてブロンズは会員登録した全員、シルバーは3万円以上、ゴールドは10万円以上とします。金額はストアの客単価に合わせて決めてください。
  • 特典:ランク別の割引率(例:シルバー3%、ゴールド5%)、送料無料、限定商品の公開など。ここでは割引率を扱います。
  • ランクが下がる条件:期間制にすると、購入が途絶えたお客様のランクは下がります。下がることを会員規約や案内ページに明記しておくと、トラブルを防げます。

ゲスト購入の注文はユーザーに紐付かないため、ランクの対象外になります。ランク制度を始めるなら、会員登録を促す導線も合わせて見直してください。

ランクを判定する関数

まずは、ユーザーIDを受け取って直近12か月の購入額を計算し、ランクを返す関数を作ります。注文の取得には wc_get_orders() を使います。HPOS(高性能注文ストレージ)が有効なストアでも同じコードで動くためです。

<?php
// 子テーマの functions.php、または wp-content/mu-plugins/my-member-rank.php に置く。

defined( 'ABSPATH' ) || exit;

/**
 * ランクの定義。上から順に判定する。
 */
function my_rank_levels() {
	return array(
		'gold'   => array( 'label' => 'ゴールド', 'min' => 100000, 'discount' => 5 ),
		'silver' => array( 'label' => 'シルバー', 'min' => 30000,  'discount' => 3 ),
		'bronze' => array( 'label' => 'ブロンズ', 'min' => 0,      'discount' => 0 ),
	);
}

/**
 * 直近12か月の完了済み注文の合計額(返金を除く)。
 */
function my_rank_spent_last_year( $user_id ) {
	$order_ids = wc_get_orders( array(
		'customer_id'  => $user_id,
		'status'       => array( 'wc-completed' ),
		'date_created' => '>' . ( time() - YEAR_IN_SECONDS ),
		'limit'        => -1,
		'return'       => 'ids',
	) );

	$total = 0;
	foreach ( $order_ids as $order_id ) {
		$order = wc_get_order( $order_id );
		if ( $order ) {
			$total += (float) $order->get_total() - (float) $order->get_total_refunded();
		}
	}
	return $total;
}

/**
 * 購入額からランクのキーを決めて保存する。
 */
function my_rank_recalculate( $user_id ) {
	$user_id = absint( $user_id );
	if ( ! $user_id ) {
		return;
	}
	$spent = my_rank_spent_last_year( $user_id );
	foreach ( my_rank_levels() as $key => $level ) {
		if ( $spent >= $level['min'] ) {
			update_user_meta( $user_id, 'my_member_rank', $key );
			return;
		}
	}
}

判定に「完了」ステータスだけを使うのは、「処理中」の注文はまだ発送前で、キャンセルされる可能性があるからです。代金引換など入金確認が後になる決済方法を扱うストアでは、特にこの区別が効きます。

注文の状態が変わったらランクを更新する

ランクは注文が完了したとき、返金されたときに計算し直します。ページを表示するたびに計算すると、注文の多いお客様ほどページが重くなるため、結果をユーザーメタに保存しておき、表示や割引ではその値を読むだけにします。

/**
 * 注文完了・返金・キャンセル時にランクを再計算する。
 */
function my_rank_on_order_change( $order_id ) {
	$order = wc_get_order( $order_id );
	if ( $order && $order->get_customer_id() ) {
		my_rank_recalculate( $order->get_customer_id() );
	}
}
add_action( 'woocommerce_order_status_completed', 'my_rank_on_order_change' );
add_action( 'woocommerce_order_status_refunded', 'my_rank_on_order_change' );
add_action( 'woocommerce_order_status_cancelled', 'my_rank_on_order_change' );
add_action( 'woocommerce_order_refunded', 'my_rank_on_order_change' ); // 一部返金

期間制の場合、購入が無くても12か月経てばランクは下がるはずですが、上のコードは注文の変化が無いと再計算しません。月に1回程度、WP-Cron(または Action Scheduler)で会員を少しずつ再計算する処理を加えるか、「ランクは注文完了時に更新されます」と案内するかを決めておきます。会員数が多い場合、一度に全員を処理するとタイムアウトしやすいので、数百人ずつに分けて処理します。

既存の会員に初回のランクを付けるときも同じ考え方です。WP-CLI が使えるなら wp eval で数人ずつ試してから全体に広げると、計算結果の確認がしやすくなります。作業前にはデータベースのバックアップを取ってください。

ランクに応じてカートで割引する

割引は woocommerce_cart_calculate_fees でマイナスの手数料を追加する方法が、既存の商品価格やクーポンの仕組みに手を入れずに済み、扱いやすい方法です。

/**
 * ランク別の割引をカートに追加する。
 */
function my_rank_cart_discount( $cart ) {
	if ( is_admin() && ! wp_doing_ajax() ) {
		return;
	}
	if ( ! is_user_logged_in() ) {
		return;
	}

	$rank   = get_user_meta( get_current_user_id(), 'my_member_rank', true );
	$levels = my_rank_levels();
	if ( empty( $levels[ $rank ] ) || ! $levels[ $rank ]['discount'] ) {
		return;
	}

	$rate     = $levels[ $rank ]['discount'];
	$discount = round( $cart->get_subtotal() * $rate / 100 );
	if ( $discount > 0 ) {
		$cart->add_fee(
			sprintf( '%s会員割引(%d%%)', $levels[ $rank ]['label'], $rate ),
			-$discount,
			false
		);
	}
}
add_action( 'woocommerce_cart_calculate_fees', 'my_rank_cart_discount' );

ここでつまずきやすいのが税の扱いです。add_fee() の3つ目の引数は手数料を課税対象にするかどうかの指定で、false(非課税)にすると割引分の税は調整されず、税額は割引前の商品価格で計算されたままになります。true にする場合は、どの税区分で調整するかも合わせて確認が必要です。税込表示のストアでどう計上するかは、会計の担当者や税理士と相談したうえで、課税設定を合わせてください。クーポンとの併用を認めるか、セール商品も対象にするかも、ここで条件を加えて調整します。

マイアカウントでランクを表示する

お客様が自分のランクを確認できると、制度が伝わりやすくなります。マイアカウントのダッシュボードには woocommerce_account_dashboard アクションで追記できます。

function my_rank_dashboard_notice() {
	$rank   = get_user_meta( get_current_user_id(), 'my_member_rank', true );
	$levels = my_rank_levels();
	if ( empty( $levels[ $rank ] ) ) {
		return;
	}
	printf(
		'<p class="my-member-rank">現在の会員ランク:<strong>%s</strong></p>',
		esc_html( $levels[ $rank ]['label'] )
	);
}
add_action( 'woocommerce_account_dashboard', 'my_rank_dashboard_notice' );

表示する値は自前の定義から取っていますが、出力時は esc_html() でエスケープしておきます。後からランク名を管理画面で編集できるようにしたときにも、そのまま安全に使えます。

確認方法

ステージング環境で、テスト用の会員アカウントを作り、決済サービスのテストモードで注文して次を確かめます。

  1. 注文を「完了」にした後、ユーザーメタ my_member_rank が想定のランクになる(wp user meta get <ユーザーID> my_member_rank で確認できます)。
  2. 返金するとランクが下がる。
  3. カートに割引行が表示され、合計と税額が想定どおりになる。
  4. ログアウト状態やゲストでは割引が付かない。

プラグインで済ませる場合

自前で作らずに済ませたい場合は、会員制のWooCommerce拡張(公式の WooCommerce Memberships など)や、ポイント・ロイヤリティ系のプラグインが選択肢になります。ただし、購入額による自動昇格に対応しているか、期間制にできるか、HPOSに対応しているかは製品と版によって違います(2026年10月現在)。導入前に公式ドキュメントで確認し、ステージングで試してください。

まとめ

  • ランクの判定基準・しきい値・特典・降格条件を先に文章で決める。
  • 判定は wc_get_orders() で完了済み注文を集計し、返金分を差し引く。結果はユーザーメタに保存する。
  • 再計算は注文の完了・返金・キャンセル時に行い、期間制なら定期処理を追加する。
  • 割引は woocommerce_cart_calculate_fees のマイナス手数料で付け、税の扱いを会計と合わせる。
  • 表示は esc_html() でエスケープし、テストモードとステージングで確認してから本番に入れる。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲