WordPress のネットショップ構築プラグイン Welcart を使用しているショッピングサイトで、複数の施設に置いたQRコードからサイトにアクセスしてもらい、そのまま注文いただいた際に、どの施設からのアクセスによる注文かがわかるように出来ないかという相談がありました。

とりあえず思いついた方法は2つ。

  1. QRコードのURLに施設ごとに固有のパラメータを埋め込む。→ しかし、どうやってそのパラメータと注文を紐つけるか?
  2. 注文画面で施設名または施設コードを選択してもらう。→ お客様に選択してもらう手間が発生するし、必ずしもQRコードからの注文ばかりではなく任意項目なので選択されない可能性もある。

というわけで、1. のパラメータを埋め込む方法で、パラメータの値をカート画面から注文画面まで引き継ぎ、受注データに反映させることができないか、方法を探ることにしました。

ここで最近すっかりお世話になっている ChatGPT の出番です。アクセス時にパラメータをセッションに保存し、カートから購入完了までセッションから値を参照して受注メール本文に差し込むという流れですが、ChatGPT が提示するコードはフックの使い方が間違っていたり、Welcart に存在しない関数や WooCommerce の関数が混在していたりで、何度試してもPHPエラーが出たり、パラメータが取得できなかったりですんなりとはいきません。

しつこく ChatCGT とやりとりしていると、“ネットに出ているコードはほぼ信用できない” とか、“正直に言います。ここで一度、Welcart の「幻想」を全部捨てた方が早いです。” とか言ってきました。“これはあなたのミスではありません。はっきり言います。ここまであなたがハマったのは Welcart が悪いです。” とも言ってくれましたが…w

最終的に、Welcart 独自APIは一切使わず、PHPセッションだけを使い、受注メールで直接 $_SESSION を読むという結論になり、以下のコードで成功しました。

URLパラメータ名は「qr」としています。「https://example-shop.com/?qr=abc」のようなURLをQRコードに埋め込みアクセスします。

// セッション開始
add_action( 'init', function() {
	if ( ! session_id() ) {
		session_start();
	}
}, 1 );

// URLパラメータを保存
add_action( 'template_redirect', function() {
	if ( isset( $_GET['qr'] ) ) {
		$_SESSION['qr_param'] = sanitize_text_field( $_GET['qr'] );
	}
});

// カート画面〜内容確認画面で表示(確認のため・本番運用では不要)
function monobe_display_qr_param() {
	if ( empty( $_SESSION['qr_param'] ) ) {
		return;
	}
	echo '<div class="qr-info">';
	echo '<p>QRパラメータ:' . esc_html( $_SESSION['qr_param'] ) . '</p>';
	echo '</div>';
}

add_action(
	'usces_action_cart_page_footer',
	'monobe_display_qr_param'
);

add_action(
	'usces_action_customer_page_footer',
	'monobe_display_qr_param'
);

add_action(
	'usces_action_delivery_page_footer',
	'monobe_display_qr_param'
);

add_action(
	'usces_action_confirm_page_footer',
	'monobe_display_qr_param'
);

// 受注メールに表示
add_filter(
	'usces_filter_send_order_mail_body',
	function( $body, $order ) {
		if ( ! empty( $_SESSION['qr_param'] ) ) {
			$body .= "\n\n";
			$body .= "■ QRパラメータ:";
			$body .= $_SESSION['qr_param'];
			$body .= "\n\n";
		}
		return $body;
	},
	10,
	2
);

// 注文完了ページでセッションを破棄する
add_action( 'template_redirect', function() {
	if ( ! session_id() ) {
		return;
	}
	if ( function_exists( 'ag_is_welcart_page' ) && ag_is_welcart_page( 'ordercompletion' ) ) {
		unset( $_SESSION['qr_param'] );
	}
});

これで受注メールにパラメータの値を埋め込むことはできました。ただ、これでは Welcart の受注データには反映されませんので、受注リスト画面で検索したり、CSV に吐き出したりすることができません。件数が少なければ受注メールから管理者メモ欄等に手入力という運用でもよいのですが。

そこでふと、カスタムオーダーフィールドが使えるのではないかと気がつきました。カスタムオーダーフィールドで「QRパラメータ」のテキストフィールドを作成し、注文画面でセッションから値を自動挿入すればいいわけです。

これもまた ChatGPT に聞くとなかなかうまくいかず、何度か “確実に動くコード” や “最終形” を経て、最終的に JavaScript でフィールドに値を挿入することで落ち着きました。

前提として、カスタムオーダーフィルドはフィールドキーを「qr_param」とし、フィールドタイプは「テキスト」で作成します。

// カスタムオーダーフィールドに自動挿入
add_action( 'wp_footer', function () {
	if ( empty( $_SESSION['qr_param'] ) ) return;
	?>
	<script>
	document.addEventListener('DOMContentLoaded', function () {
		const field = document.querySelector('[name="custom_order[qr_param]"]');
		if (field && !field.value) {
			field.value = <?php echo json_encode( $_SESSION['qr_param'] ); ?>;
		}
	});
	</script>
	<?php
});

カスタムオーダーフィルドはデフォルトで受注メールに表示されますので、先のコードの「受注メールに表示」の部分は不要になります。

最後の仕上げとして、このカスタムオーダーフィルドを注文画面から非表示にします。
配送・支払い方法画面はテーブルの行にクラスが付いてますので CSS で非表示にできます。

#custom_order .customkey_qr_param {
	display: none;
}

内容確認画面は行を区別できる要素がありませんので、JavaScript で非表示としました。

$('#confirm_table th:contains("QRパラメータ")').closest('tr').hide();

なお、受注リスト画面で受注検索の受注情報項目の選択リストに「QRパラメータ」を反映するには、表示オプションで受注リストの列に「QRパラメータ」を表示しておく必要があります。