【Laravel】クエリパラメータ付きURLのABテストをおこなう際の注意点
先日、当サイトにてLaravelでABテストの機能を実装する手順を紹介しましたが、実装・運用後にある問題に気付きました。
アクセスされたページのURLに、以下のようなクエリパラメータが付与されていた場合、意図した通りにアクセス分散されませんでした。
https://tech.tiger-rack.co.jp/page-a?gclid=CjwK123abc456…
クエリパラメータ付きのURLの場合にもリダイレクト処理を機能させるようにするために、今回あらためてLaravelでのABテスト機能実装方法を紹介します。
アクセス振り分け処理をMiddlewareに実装
前回記事では単純なアクセス振り分けのみでしたのでControllerに処理を書きましたが、今回はMiddlewareに書きます。
まずはartisanコマンドでMiddlewareを作成しましょう。
php artisan make:middleware AbTestRedirect
Controllerファイルが作成されたら以下のようにファイルを更新します。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class AbTestRedirect
{
/** @var array ABテストパターン */
private const AB_TEST_PATTERNS = [
[
'test_name' => 'top_ab_test',
'target_path' => '/page-a',
'redirect_path_b' => '/page-b',
'cookie_name' => 'top_ab_test_group',
],
];
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
foreach (self::AB_TEST_PATTERNS as $test) {
// 今のリクエストが対象か確認
if (trim($request->path(), '/') === trim($test['target_path'], '/')) {
$cookie_name = $test['cookie_name'];
// グループ取得 or 新規割当
$group = $request->cookie($cookie_name);
if (!$group) {
$group = rand(0, 1) ? 'A' : 'B';
cookie()->queue(cookie($cookie_name, $group, 60 * 24 * 14)); // 14日間
}
// Bグループならリダイレクト
if ($group === 'B') {
$queryString = $request->getQueryString();
$redirectUrl = $test['redirect_path_b'] . ($queryString ? '?' . $queryString : '');
return redirect($redirectUrl);
}
// Aグループ or cookieありならそのまま
break; // 他のABテストは無視(1つのリクエストに対して1テストだけ適用)
}
}
return $next($request);
}
}
まず、リダイレクトルールをクラス定数AB_TEST_PATTERNSに定義します。
これで複数のABテストのルールを1ファイルにまとめて定義することができ、テストごとにコントローラファイルを編集する必要がなくなりました。
その他、リダイレクトテストにおける以下の基礎的な処理は前回記事で紹介したとおりです。
- 50%の確率でAパターン、Bパターンそれぞれに振り分ける
- 一度AパターンにアクセスしたユーザーにCookieを付与し、2度目のアクセスの際もAパターンを表示させる
次にKernel.phpに、作成したミドルウェアを登録します。
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
...
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array<string, class-string|string>
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
...
'ab_test' => \App\Http\Middleware\AbTestRedirect::class,
];
最後にルーティングファイル(web.php)を修正して完了です。
今回は「/page-a」を振り分け対象のLPとしたため、page_aのみab_testミドルウェアの処理を入れるようにしています。
Route::view('/page-a', 'page_a')->name('page_a')->middleware('ab_test');
Route::view('/page-b', 'page_b')->name('page_b');
これでクエリパラメータ付きURLへのアクセスにも対応することができ、さらに複数のABテストを同時に行う際の保守性も高まったりと、LaravelでのABテスト処理を改善することができました。
このカテゴリの最新記事
2023.06.30
2024.02.14
2024.12.06
2023.09.04