<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Will Pearse]]></title><description><![CDATA[Will Pearse]]></description><link>http://wpearse.com/</link><image><url>http://wpearse.com/favicon.png</url><title>Will Pearse</title><link>http://wpearse.com/</link></image><generator>Ghost 4.48</generator><lastBuildDate>Tue, 07 Apr 2026 20:13:58 GMT</lastBuildDate><atom:link href="http://wpearse.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Checkmango]]></title><description><![CDATA[<p>Our signup flow has three steps:</p><ol><li>Email address and password</li><li>Personalisation (segmentation) questions</li><li>Email verification</li></ol><p>We&apos;re seeing a steep (40% abandonment) drop-off at step 2: many users are entering their email address and creating a password, and then just can&apos;t be bothered with the personalisation questions.</p>]]></description><link>http://wpearse.com/checkmango/</link><guid isPermaLink="false">62fc16a38c418a04b6c4183b</guid><dc:creator><![CDATA[Will Pearse]]></dc:creator><pubDate>Wed, 17 Aug 2022 06:52:07 GMT</pubDate><content:encoded><![CDATA[<p>Our signup flow has three steps:</p><ol><li>Email address and password</li><li>Personalisation (segmentation) questions</li><li>Email verification</li></ol><p>We&apos;re seeing a steep (40% abandonment) drop-off at step 2: many users are entering their email address and creating a password, and then just can&apos;t be bothered with the personalisation questions. </p><p>Our hypothesis (an absolute no-brainer, a door knob would struggle to think up worse) is that by removing step 2, we&apos;ll get a whole heap more people completing the signup flow.</p><p>I came across <a href="https://checkmango.com">checkmango.com</a> which promises an easy way to do A/B testing &#x2013; perfect for what we want.</p><p>This post documents our setup and use of Checkmango inside our Laravel app.</p><h3 id="experiment-setup">Experiment Setup</h3><p>After registering for a Checkmango account I created a new experiment: <code>test_signup_hide_personalisation</code>.</p><p>The experiment has two variants:</p><ol><li><code>var_signup_show_personalisation</code> the control variant (what we&apos;re doing already)</li><li><code>var_signup_hide_personalisation</code> the new variant we&apos;re going to test</li></ol><p>I chose a 50-50 split (&quot;equal distribution&quot;) for participants, and the goal (&quot;primary metric&quot;) I created was <code>signup_complete</code>.</p><p>Click &quot;Start&quot; in the Checkmango dashboard to begin your experiment.</p><h3 id="install-the-php-sdk">Install the PHP SDK</h3><p>Installing the SDK is as simple as: <code>composer require checkmango/phpsdk</code>. The documentation for the SDK lives here: <a href="https://github.com/checkmango/php-sdk">github.com/checkmango/php-sdk</a>. I pinned my version of the SDK to <code>dev-master</code>.</p><h3 id="creating-participants">Creating Participants</h3><p>Each Checkmango Participant need to be identified using a unique string (not a numerical ID). We&apos;re using the format <code>cm_{userId}</code> as it&apos;s a string, easily reproducible, and doesn&apos;t need another database column. This works for us, you might want to do something different.</p><p>To create a participant:</p><pre><code class="language-PHP">$client = new Checkmango\Client();
$client-&gt;authenticate($apiKey);

$participantId = &apos;...&apos;; // You figure this out

$client-&gt;teams($teamId)-&gt;participants()-&gt;create([
	&apos;key&apos; =&gt; $participantId,
]);</code></pre><p>This API call takes ~1 second to complete. I think you&apos;re best to complete this in a queued job, but you could do the request inline if you&apos;re desperate (or running the experiment early in a user&apos;s journey).</p><h3 id="enrol-the-participant-in-an-experiment">Enrol the Participant in an Experiment</h3><p><em>To pre-empt any confusion: I code in Queen&apos;s English, so I&apos;m using <code>enrol</code>. If you speak North American your native spelling is <code>enroll</code>. </em></p><p>Each time a user is created in our application (in step 1 of our signup flow) we need to enrol the participant in our experiment:</p><pre><code class="language-PHP">$client-&gt;teams($teamId)
	-&gt;experiments()
	-&gt;enrol(&apos;test_signup_hide_personalisation&apos;, $participantId);</code></pre><p>This API call returns the enrollment information, which includes the variant that we should show to the user. Checkmango decides the variant for us, based on the algorithm that we chose when we setup the experiment.</p><pre><code class="language-JSON">[
  &quot;id&quot; =&gt; &quot;cm_...&quot;,
  &quot;type&quot; =&gt; &quot;participants&quot;,
  &quot;attributes&quot; =&gt; [
    ...
    &quot;enrollments&quot; =&gt; [
      &quot;test_signup_hide_personalisation&quot; =&gt; &quot;var_signup_show_personalisation&quot;,
    ],
    ...
  ],
  ...
]</code></pre><p>In our case, Checkmango tells us the user should be shown the <code>var_signup_show_personalisation</code> variant (or, shown step 2 in our sign up flow).</p><h3 id="remember-which-variant-the-participant-sees">Remember which Variant the Participant sees</h3><p>We set up a simple database table to keep track of which users are in which experiments, and which variant for each experiment the user should see. You might want to do something similar.</p><pre><code class="language-PHP">Schema::create(&apos;checkmango_variants&apos;, function (Blueprint $table) {
    $table-&gt;id();
    $table-&gt;foreignId(&apos;user_id&apos;);
    $table-&gt;string(&apos;experiment&apos;)-&gt;index();
    $table-&gt;string(&apos;variant&apos;)-&gt;index();
    $table-&gt;timestamps();
});</code></pre><p>When we&apos;ve enrolled the participant in an experiment, we then record the all the user&apos;s experiments and variants like so:</p><pre><code class="language-PHP">$data = $client-&gt;teams($teamId)
	-&gt;experiments()
	-&gt;enrol($experiment, $participantId);

$enrolments = data_get($data, &apos;attributes.enrollments&apos;);

foreach ($enrolments as $experiment =&gt; $variant) {
    CheckmangoVariant::updateOrCreate(
        [
            &apos;user_id&apos; =&gt; $user-&gt;id,
            &apos;experiment&apos; =&gt; $experiment,
        ],
        [
            &apos;variant&apos; =&gt; $variant,
        ]
    );
}</code></pre><p>You can recall the variant the user should see for a given experiment quickly:</p><pre><code class="language-PHP">public static function variant(User $user, string $experiment)
{
    $variant = CheckmangoVariant::where([
        &apos;user_id&apos; =&gt; $user-&gt;id,
        &apos;experiment&apos; =&gt; $experiment,
    ])-&gt;first();
    return $variant ? $variant-&gt;variant : false;
}</code></pre><h3 id="using-the-variant">Using the Variant</h3><p>Our Blade templates we check which variant the user should be seeing, and make adjustments as required. In our controller:</p><pre><code>return view(&apos;template&apos;, [
    &apos;variant&apos; =&gt; Checkmango::variant($user, $experiment),
    ...
]);</code></pre><p>And in our Blade template, remembering that <code>var_signup_show_personalisation</code> is our control:</p><pre><code>@if (! $variant || $variant === &apos;var_signup_show_personalisation&apos;)

	{{-- show personalisation, control --}}

@else

	{{-- hide personalisation --}}

@endif</code></pre><h3 id="tracking-impressions">Tracking Impressions</h3><p>WIP</p>]]></content:encoded></item></channel></rss>