Laravel で「カスタマージャーニー」を意識したメルマガ登録をつくる

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、まだまだマーケティングの勉強をLaravelに活かしたい今日この頃です。

前回の記事の続きなのですが、また新たなマーケティング用語に出会いました。

それは・・・・・・

カスタマージャーニー

です。

カスタマージャーニーとは、簡単に言うと「お客さんがどんな流れで購入するの❓」です。

例えば、ブログやYouTubeから来た人なら、より深い知識を学ぼうという意識が強い反面、インスタグラムなら「もっと軽い気持ち」で訪問しそうです。

また、広告経由なら、出稿条件が決まっていれば「富裕層が多いから単価が高いものを提案しよう」という具合にセールスに活かすことができるわけですね。

そこで❗

今回はこのカスタマージャーニーを意識して「流入経路」を活かしたメルマガ登録機能をLaravelで作ってみることにしました。

ぜひ何かの参考になりましたら嬉しいです。😄✨

「カスタマージャーニー
ってなんか
昔のヒットソングみたいですね」

開発環境: Laravel 10.x

前提として

今回は前回記事の続きになっています。

そのため、テーブル構造は前回のものを踏襲したものになっているので気をつけてください。(マイグレーションが後から追加になってるカンジです)

もしご覧になっていない方は、以下から「DBまわり」だけは完了させてからこちらをお読みください。

📝 参考ページ: Laravel で「ダイレクト・レスポンス・マーケティング」基礎システムをつくる

やりたいこと

今回は、「どこ経由で流入してきたメルマガユーザーなのか?」が分かるように「流入経路」の情報をDBテーブルに保存するようにします。

ただ、それだけでは面白くないので、メルマガ登録したらその流入経路に関連する商品の割引クーポンを送信することにしてみます。

では、今回も楽しんでやっていきましょう❗

カスタマージャーニーの種類の Enum をつくる

まずは「どこ経由のサイト流入か」のタイプを定義しておいて、いつでも取り出せるようにしておきましょう。

今回用意するのは、以下3つのカスタマージャーニーです。

  • メール経由
  • ブログ経由
  • 広告経由

app/Enums/CustomerJourneyType.php

<?php

namespace App\Enums;

enum CustomerJourneyType: int
{
    case From_Email = 1;    // メール経由
    case From_Blog = 2;     // ブログ経由
    case From_Ads = 3;      // 広告経由
}

どこ経由のサイト流入かを Cookie にセットするミドルウェアをつくる

訪問ユーザがサイトに来てすぐメルマガ登録してくれたら問題はないですが、実際は別のページを見たりすると思います。

なので、どんな場合でも「どこ経由のサイト流入か?」が分かるようにCookieに値を保存しておくことにします。

以下のコマンドを実行してください。

php artisan make:middleware CustomerJourneyMiddleware

すると、ミドルウェア・ファイルが作成されるので中身を以下のようにします。

app/Http/Middleware/CustomerJourneyMiddleware.php

<?php

namespace App\Http\Middleware;

use App\Enums\CustomerJourneyType;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class CustomerJourneyMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if($request->filled('cj')) {

            $customer_journey_type = CustomerJourneyType::from($request->cj);

            if(! is_null($customer_journey_type)) { // カスタマージャーニーが存在する場合

                $minutes = 60 * 24 * 365 * 10; // 10年間
                cookie()->queue('customer_journey', $customer_journey_type->value, $minutes);

            }

        }

        return $next($request);
    }
}

ミドルウェアはつくっただけでは有効にならないので、Kernel.phpにセットします。

app/Http/Kernel.php

// 省略

class Kernel extends HttpKernel
{
    // 省略

    protected $middlewareGroups = [
        'web' => [

            // 省略

            \App\Http\Middleware\CustomerJourneyMiddleware::class,
        ],

// 省略

これで、サイト内のどこに来てもこのミドルウェアが実行されることになります。(APIは除く)つまり、わざわざルート内でミドルウェアをセットする必要はありません。

カラムを追加するマイグレーションをつくる

では、「前提として」に書いたとおり前回作成したテーブルに新しいカラム「customer_journey_type」を追加するマイグレーションをつくりましょう。

以下のコマンドを実行してください。

php artisan make:migration add_customer_journey_type_to_newsletter_users

すると、マイグレーション・ファイルが作成されるので中身を以下のように変更します。

database/migrations/****_**_**_******_add_customer_journey_type_to_newsletter_users.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::table('newsletter_users', function (Blueprint $table) {
            $table->unsignedInteger('customer_journey_type') // App\Enums\CustomerJourneyType
                ->nullable()
                ->after('email');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::table('newsletter_users', function (Blueprint $table) {
            $table->dropColumn('customer_journey_type');
        });
    }
};

では、データベースを初期化しておきます。
以下のコマンドを実行してください。

php artisan migrate:fresh --seed

すると、実際のテーブルはこうなりました。

メール部分をつくる

では、コントローラーをつくる前にその中で使うことになるMailable(メール送信部分)をつくっていきましょう。

以下のコマンドを実行してください。

php artisan make:mail NewsletterUserRegistered

するとファイルが作成されるので、中身を以下のようにします。

app/Mail/NewsletterUserRegistered.php

<?php

namespace App\Mail;

use App\Enums\CustomerJourneyType;
use App\Models\NewsletterUser;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class NewsletterUserRegistered extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     */
    public function __construct(private NewsletterUser $newsletter_user)
    {
    }

    /**
     * Get the message envelope.
     */
    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'メルマガ登録ありがとうございました!',
        );
    }

    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        $is_cj_email = $this->newsletter_user->customer_journey_type === CustomerJourneyType::From_Email->value;
        $is_cj_blog = $this->newsletter_user->customer_journey_type === CustomerJourneyType::From_Blog->value;
        $is_cj_ads = $this->newsletter_user->customer_journey_type === CustomerJourneyType::From_Ads->value;

        return new Content(
            view: 'emails.newsletter_user_registered',
            with: [
                'newsletter_user' => $this->newsletter_user,
                'is_cj_email' => $is_cj_email,
                'is_cj_blog' => $is_cj_blog,
                'is_cj_ads' => $is_cj_ads,
            ],
        );
    }

    /**
     * Get the attachments for the message.
     *
     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
     */
    public function attachments(): array
    {
        return [];
    }
}

ではメールのビューもつくりましょう。
以下のコマンドを実行してください。

php artisan make:view emails.newsletter_user_registered

作成されたファイルを変更します。

resources/views/emails/newsletter_user_registered.blade.php

{{ $newsletter_user->name }}さん、メルマガ登録ありがとうございます。<br><br>

(本文は省略)<br><br>

なお、登録していただいた特典として、以下の割引クーポンをお送りいたします。<br>
ぜひ、次回のご来店時にご利用ください。<br><br>

@if($is_cj_email === true)
    15% OFF クーポンをここに表示<br><br>
@elseif($is_cj_blog === true)
    10% OFF クーポンをここに表示<br><br>
@elseif($is_cj_ads === true)
    5% OFF クーポンをここに表示<br><br>
@endif

今後とも「Sukohi ECショップ」をよろしくお願いいたします。

ちなみに、この中ではCPA(1人のお客さん獲得のコスト)が安いカスタマージャーニーの場合は、より割引率が高いクーポンを配布するイメージになってます。

コントローラーをつくる

では、次にメルマガに登録する部分を作っていきましょう。
以下のコマンドを実行してください。

php artisan make:controller NewsletterController

するとファイルが作成されるので、中身を以下のようにします。

app/Http/Controllers/NewsletterController.php

<?php

namespace App\Http\Controllers;

use App\Enums\CustomerJourneyType;
use App\Mail\NewsletterUserRegistered;
use App\Models\NewsletterUser;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;

class NewsletterController extends Controller
{
    public function create()
    {
        return view('newsletter.create');
    }

    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|max:255|unique:newsletter_users,email',
        ]);

        // メルマガ登録
        $newsletter_user = new NewsletterUser();
        $newsletter_user->uuid = Str::uuid();
        $newsletter_user->name = $request->name;
        $newsletter_user->email = $request->email;
        $newsletter_user->customer_journey_type = (int) $request->cookie('customer_journey');
        $newsletter_user->save();

        // メール送信
        Mail::to($newsletter_user->email)->send(new NewsletterUserRegistered($newsletter_user));

        return '登録が完了しました';
    }
}

ビューをつくる

続いて、さっきのコントローラーの中で使った「ビュー」をつくります。
以下のコマンドを実行してください。

php artisan make:view newsletter.create

すると、ファイルが作成されるので中身を変更します。

resources/views/newsletter/create.blade.php

<html>
<body>
    <h1>メルマガ登録</h1>
    <form method="POST" action="{{ route('newsletter.store') }}">
        @csrf
        <div>
            <label for="name">名前</label>
            <br>
            <input type="text" id="name" name="name" required>
        </div>
        <div>
            <label for="email">メールアドレス</label>
            <br>
            <input type="email" id="email" name="email" required>
        </div>
        <div style="padding:15px 0;">
            (本来はオプトインの同意を取る必要がありますが、今回は省略します)
        </div>
        <div>
            <button type="submit">登録する</button>
        </div>
    </form>
</body>
</html>

ルートをつくる

では、最後にルートです。
以下のようにしてください。

routes/web.php

// 省略

use App\Http\Controllers\NewsletterController;

// 省略

Route::prefix('newsletter')->controller(NewsletterController::class)->group(function(){

    Route::get('create', 'create')->name('newsletter.create');
    Route::post('store', 'store')->name('newsletter.store');

});

これで作業は完了です。
お疲れ様でした。😄

テストしてみる

では、実際に以下の手順でメルマガに登録してみます。

  1. まずトップページに「カスタマージャーニー」番号をつけてアクセスする
  2. メルマガ登録ページへ移動
  3. フォームから必要事項を入力して送信
  4. 登録完了後、データベースにカスタマージャーニー番号が入っているかチェック
  5. メールが送信されているかチェック

では、まずはブラウザでトップページ + カスタマージャーニー番号をつけたURLhttps://******/?cj=2」(👈 つまり、ブログ経由)にアクセスします。

すると・・・・・・

はい❗

我々Laravel開発者にはおなじみのトップページが表示されました。

では、この状態でブラウザにCookieが登録されているかチェックしておきましょう。

ちゃんと「customer_journey」が登録されています。

※ なお、数字じゃないのはLaravelが暗号化してくれているからです。取り出すときは数字になります。

では、次にメルマガ登録フォームの「https://******/newsletter/create」へ移動して必要事項を入力し、送信してみましょう。

うまくいくでしょうか・・・・・・

はい❗
うまく登録完了メッセージが表示されました。

では、DBテーブルの方も確認しておきましょう。

はい❗

ちょっとわかりにくいかもですが、新しいデータが登録され「カスタマージャーニー」番号も保存されています。

では、最後にメールがどうなっているか確認しておきましょう。

こちらも、メールが送信されて割引クーポンは「ブログ経由」のものになっています。

すべて成功です😄✨

企業様へのご提案

今回は「オンラインショップ」を想定してカスタマージャーニーを活用してみましたが、オンラインショップでなくても「どこからサイト流入したのか?」を活用して以下のような対策をすると、よりCVR向上やコストの削減につなげることができます。

  • 問い合わせがあった: 流入元の CPA をカスタマージャーニーごとに割り出し、あまり効果的に集客できていない場合は改善する、もしくは廃止を検討する
  • 無料ファイルがダウンロードされた: 流入元によってどの程度の範囲のサービスを求めているかが分かる
  • 資料請求があった: 顧客の好みによって提案する資料を変更する

などなど。

もしこういった施策を実装したい場合はお問い合わせからご相談ください。

お待ちしております。😄✨

開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで、今回は「カスタマージャーニー」を意識したメルマガ機能を実装してみました。

これまでマーケティングの勉強をしていないときは、こんなやり方は想像もしていませんでしたが、企業は「より売上を上げるためにここまでのことをしてるんだな」と関心しました。

頭のいい人ってすごいですね。

私もそういう人たちのテクニックをパクってより価値のあるものをクライアントに提供できるようにしていきます。

みなさんもぜひいろいろと考えてみてくださいね。

ではでは〜❗

「マーケティングを子供の頃に
教わってたらな〜
いや、拳法とかしか興味ないから無理か(笑)」

 

このエントリーをはてなブックマークに追加       follow us in feedly