<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Emil Kovacevic</title>
    <description>The latest articles on DEV Community by Emil Kovacevic (@emilkovacevic).</description>
    <link>https://dev.to/emilkovacevic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F993625%2F46efe6fd-6ae9-4fe3-9bdc-ed2ff06b9e0f.jpeg</url>
      <title>DEV Community: Emil Kovacevic</title>
      <link>https://dev.to/emilkovacevic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/emilkovacevic"/>
    <language>en</language>
    <item>
      <title>How to implement A/B testing in Ionic</title>
      <dc:creator>Emil Kovacevic</dc:creator>
      <pubDate>Wed, 21 Dec 2022 17:00:00 +0000</pubDate>
      <link>https://dev.to/emilkovacevic/how-to-implement-ab-testing-in-ionic-9eg</link>
      <guid>https://dev.to/emilkovacevic/how-to-implement-ab-testing-in-ionic-9eg</guid>
      <description>&lt;p&gt;The world population continues to grow, and so does the number of house pets. While we all hope most of them have a good quality of life, some don't have a home. To combat this, we can make an animal care app. In this blog post, the app's objective is to increase the pet adoption rate. We will change the color of our call-to-action button and measure the click-through rate of each button version using A/B testing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OyXAQlao--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvmlhl1kb0c7xwhogbxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OyXAQlao--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvmlhl1kb0c7xwhogbxu.png" alt="Comparisons" width="512" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is A/B testing?
&lt;/h2&gt;

&lt;p&gt;A/B testing is a way to track the performance of two versions of the same thing without conveying our experiment to the users by using feature flags, which let you launch new features and change your software configuration without (re)deploying code.&lt;/p&gt;

&lt;p&gt;The test should include only one change. We want to know the effect of the difference reliably. If we change several things, we cannot distinguish the personal impact of each. In this case, half of the users get the old version of the button (this version is also known as control), and the other half get the new (the variant). Then we measure the number of clicks on each and compare them. We are essentially performing user segmentation and measuring the growth potential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the A/B testing app
&lt;/h2&gt;

&lt;p&gt;You can find the complete project on &lt;a href="https://github.com/configcat-labs/ab-testing-in-ionic-sample"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;basic understanding of React&lt;/li&gt;
&lt;li&gt;basic understanding of Ionic&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting up ConfigCat
&lt;/h3&gt;

&lt;p&gt;ConfigCat is a developer-centric feature flag service that helps you turn features on and off, change their configuration, and roll them out gradually to your users. It supports targeting users by attributes, percentage-based rollouts, and segmentation. Available for all major programming languages and frameworks, it can be licensed as SaaS or self-hosted for all major programming languages and frameworks. GDPR and ISO 27001 compliant.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To segment users in &lt;a href="https://configcat.com"&gt;ConfigCat&lt;/a&gt;, we first need to enable VariationIDs in our ConfigCat panel to support A/B testing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AgRoLeuP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pkqu3oacwoihfqa81s97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AgRoLeuP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pkqu3oacwoihfqa81s97.png" alt="EnableIds" width="512" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enable the segmentation feature by adding the % option. Please set it to 50%, and don’t forget to save and publish the changes. Now we have an even distribution of our buttons to the users.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--anwPHRnX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s7rl4ia3hmnwjsavvc0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--anwPHRnX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s7rl4ia3hmnwjsavvc0x.png" alt="segmentation" width="512" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ConfigCat should have a user identifier when targeting users. Usually, we get this from a server backend. For tutorial purposes, we’ll hard code a user identifier. To simulate a new user, just change the value. This will help simulate users landing in either the variant or control versions of the app.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const USER_ID =  "someUserId1234"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Implement the ConfigCat sdk in your code.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { value: isNewColorEnabled, loading } = useFeatureFlag(
"Isnewcolorenabled",
False,
{identifier: USER_ID}
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;isNewColorEnabled&lt;/strong&gt; determines which button color the user will get.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting to Amplitude
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install Amplitude in your project with the command line.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install amplitude-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create an account &lt;a href="https://analytics.amplitude.com/signup"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Select JavaScript SDK&lt;/li&gt;
&lt;li&gt;Grab the key and click next.&lt;/li&gt;
&lt;li&gt;Set the key in the project.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const AMPLITUDE_KEY = "[insert-aplitude-key-here]";
let AmplitudeInstance = amplitude.getInstance().init(AMPLITUDE_KEY);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating the UI components and adding logic to them.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  First render
&lt;/h4&gt;

&lt;p&gt;We don't want to display any content before the flag is received. To prevent odd behavior, we should add a conditional to check if the flag is ready.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{loading ?
( &amp;lt;IonLabel&amp;gt;Fetching content&amp;lt;/IonLabel&amp;gt; )
:
( &amp;lt;&amp;gt;  **show the page** &amp;lt;&amp;gt; )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Creating the rest of UI components.
&lt;/h4&gt;

&lt;p&gt;First let's create the button component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Button:React.FC&amp;lt;Props&amp;gt; = ({USER_ID, AmplitudeInstance, button_color, setShowToast}) =&amp;gt;{

const handleClick = (button_color: string): void =&amp;gt; {
amplitude.getInstance(AmplitudeInstance as any).setUserId(USER_ID);
amplitude.getInstance(AmplitudeInstance).logEvent(`user clicked: ${button_color} `);
};

const [color, setColor] = useState('color')

useEffect(() =&amp;gt; {
  if(button_color === "original"){
  setColor('medium')
  }
  else if(button_color === "variant"){
  setColor('primary')
  }
}, [button_color])

return (
  &amp;lt;IonButton
    color={`${color}`}
    expand="full"
    onClick={() =&amp;gt; {
      handleClick(button_color);
      setShowToast(true);
    }}
  &amp;gt;
    Learn How
  &amp;lt;/IonButton&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We added a handle click function to log the button click and 'useEffect' hook to set the button color.&lt;br&gt;
Back on our app page, the IsNewColorEnabled flag is used to decide which version should be served to our user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Button
USER_ID={USER_ID}
AmplitudeInstance={AmplitudeInstance}
setShowToast={setShowToast}
button_color={isNewColorEnabled ? "variant" : "original"}/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As extra features I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a hint, so we know what we are seeing for our tutorial purposes.&lt;/li&gt;
&lt;li&gt;a carousel of pets to make things nicer.&lt;/li&gt;
&lt;li&gt;additional app text to describe the purpose of the button to end users.&lt;/li&gt;
&lt;li&gt;an IonToast so we can easily see if a button is clicked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main part of the user interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{loading ? (
  &amp;lt;IonLabel&amp;gt;Fetching content&amp;lt;/IonLabel&amp;gt;
) : (
  &amp;lt;&amp;gt;
    &amp;lt;Carousel /&amp;gt;
    &amp;lt;IonCardContent className="content"&amp;gt;
      &amp;lt;IonLabel&amp;gt;
        &amp;lt;h4&amp;gt;Pet Care Center&amp;lt;/h4&amp;gt;
      &amp;lt;/IonLabel&amp;gt;
      &amp;lt;IonCardTitle&amp;gt;
        &amp;lt;h2&amp;gt;Rescue your next best friend&amp;lt;/h2&amp;gt;
      &amp;lt;/IonCardTitle&amp;gt;
      &amp;lt;p&amp;gt;Cats and Dogs, ready for a new home. Get yours today.&amp;lt;/p&amp;gt;
      &amp;lt;Button
        USER_ID={USER_ID}
          AmplitudeInstance={AmplitudeInstance}
          setShowToast={setShowToast}
          button_color={isNewColorEnabled ? "variant" : "original"}/&amp;gt;
    &amp;lt;/IonCardContent&amp;gt;
  &amp;lt;/&amp;gt;
)}&amp;lt;IonToast
          position="top"
          isOpen={showToast}
          onDidDismiss={() =&amp;gt; setShowToast(false)}
          message={isNewColorEnabled ? "variant clicked!" : "original clicked!"}
          duration={2000}
        /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the app and try to change the user identifier a few times. We should get an average 50% of the variant and 50% of the original button in our app.&lt;br&gt;
Click on the button to create some user engagement data on Amplitude.&lt;/p&gt;

&lt;h2&gt;
  
  
  Displaying analytical data on Amplitude
&lt;/h2&gt;

&lt;p&gt;Let's head back to the Amplitude &lt;a href="https://analytics.amplitude.com/login"&gt;website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;strong&gt;+new&lt;/strong&gt; button on the top left of the page, then &lt;strong&gt;Analysis&lt;/strong&gt; and finally &lt;strong&gt;Segmentation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Add the events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select Event =&amp;gt; user clicked: original&lt;/li&gt;
&lt;li&gt;Select Event =&amp;gt; user clicked: variant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tW306P0g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k6hodcrh9yq8rajtyjnv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tW306P0g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k6hodcrh9yq8rajtyjnv.png" alt="set events" width="512" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We should have a data chart on the bottom of the page. The chart shows the amount of button clicks over time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UFWox9Gs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76s86v43memifr3ov2xh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UFWox9Gs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76s86v43memifr3ov2xh.png" alt="linechart" width="512" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switch the chart to &lt;strong&gt;Bar chart&lt;/strong&gt; to see the total activity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2QAmNzXD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3a2xntt1z2a11na87ynn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2QAmNzXD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3a2xntt1z2a11na87ynn.png" alt="barchart" width="512" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the test for some time and make the final decision. Which is better? A or B ?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;We saw two things in our app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ConfigCat’s feature flags can simplify the A/B testing process. We don't need to create the logic of the even feature distribution.&lt;/li&gt;
&lt;li&gt;A/B testing helps push things in the right direction. When introducing a new feature, A/B testing gives us the user response report.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Complete code of the sample app on &lt;a href="https://github.com/configcat-labs/ab-testing-in-ionic-sample"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ConfigCat &lt;a href="https://configcat.com/docs/"&gt;docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Amplitude &lt;a href="https://www.docs.developers.amplitude.com/"&gt;docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;More on &lt;a href="https://configcat.com/blog/2022/05/02/what-is-ab-testing/"&gt;A/B testing&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find &lt;a href="https://configcat.com/"&gt;ConfigCat&lt;/a&gt; on &lt;a href="https://twitter.com/configcat"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.facebook.com/configcat"&gt;Facebook&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/configcat/"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://github.com/configcat"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ionic</category>
      <category>amplitude</category>
      <category>configcat</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
