Skip to main content

An In-depth Look into User Targeting

· 7 min read
Jan Sipos

Let's say you've just built a new feature, but it's not ready for a full release just yet. So, you decide to test it with a small group of people.

Image with sticky notes

You can go about it in two ways - deterministic or random. The first way lets you specify people by name, email, company or any other attribute you know about them. The latter uses fancy math and probability to randomly assign users into groups. Let's see how you'd accomplish both using ConfigCat.

Targeting Specific Users

Say you want to target people from your own company so your QA team can do manual testing of the new navigation. Well, you'd simply log in to your ConfigCat dashboard and set up Targeting rules using the aptly named TARGET SPECIFIC USERS feature. If everyone you wish to target is logged into your app using their email address ending in "", use the Email Attribute, with the CONTAINS Comparator and "" as the Comparison value. Setting the Served value to ON will enable anyone using that email to get the feature, while excluding everyone else. You can find detailed documentation here.

Then, from your code, you would just need to pass the User Object to a getValue call and use the boolean that gets returned (using the promise-based version here):

const client = configcat.createClient("YOUR SDK KEY HERE");
const user = new User("[email protected]");

  "newNavigation", // Feature name set up in the Dashboard
  false, // Default value
  user) // User object containing the email address
.then((isFeatureEnabled) => {
  if (isFeatureEnabled) {
    // show new navigation
  else {
    // show old navigation

This will return true for [email protected], but false for [email protected] Similarly, you can use other attributes to turn features on and off.

Don't Worry About Privacy

The data of your users never leave their device since the ConfigCat SDK evaluates Targeting rules locally. After SDK initialization, your application downloads a configuration file from the ConfigCat CDN. The configuration is then cached on the device and is the source of truth for all getValue calls. The configuration is refreshed in regular intervals (every 60 seconds by default) by making additional requests to the CDN.

This locally cached configuration contains all the Feature flags and their Targeting rules which you set up in the Dashboard so there is no need to send user's data to ConfigCat servers. However, the Targeting rules themselves could contain sensitive information, like an email address of a specific person which you want to include/exclude in your testing. This information could be exposed in a front-end application, but ConfigCat has got you covered.

When dealing with sensitive information, there are two special Comparators available in the Dashboard: IS ONE OF (Sensitive) and IS NOT ONE OF (Sensitive) (check the docs for details). Any information that is using these Comparators will be hashed by the SHA1 cryptographic hash function before it is sent to your application. This will turn "[email protected]" into "ad76509bd71dce684b8fd09f3e6b7b3f72df035b". On the application end of things, the SDK will do the same transformation locally and compare it to the value in the Targeting rule. You can verify this here. And the best part - your calls to getValue will remain the same so there's no need to change your code in any way.

If this doesn't put you at ease, you can always use a unique user ID or check sensitive info in your backend code, which won't leak information to the frontend app.

Performing a Random Test With Percentage-based Targeting

Let's say you're trying to optimize your landing page and you decide to make some changes. You're aware that simply relying on your intuition isn't enough and so you decide to get some hard data to support (or refute) your hypothesis. This is where A/B testing comes in.

You decide that 50% of your audience will get the new version and 50% will get the old version so you can track whether there is a significant change in user behavior between the two versions. Setting this up with ConfigCat is a breeze.

In your Dashboard, select the TARGET % OF USERS option and choose the On/Off Toggle Setting Kind. Input 50% for both options and you're all set. On the code side, just use getValue as before. Done.

How Are Percentages Calculated?

Just like specific targeting, percentage-based targeting is evaluated locally on the user's device. The same SHA1 function is used, this time not for information hiding (because nothing about the user travels either way) but for generating a pseudorandom string of characters. This string is actually a 40-digit hexadecimal number, from which first 7 digits are taken, converted into an integer and coerced to a range between 0-100 using the modulo operator. Let's see an example (you can check the code here):

  1. [email protected] is hashed into ad76509bd71dce684b8fd09f3e6b7b3f72df035b;
  2. ad76509 is taken from the beginning of the hash;
  3. ad76509 is parsed as 181888265;
  4. 181888265 % 100 = 65.

Since we are splitting users into two groups, 50% each, Jane will end up in the second group (she ended up at the 65th percent) and will thus receive the old version of the page.

It is possible to have more than two groups to which you can serve different text or number values. These can be further interpreted by your application to make various changes in the UI. See the docs for more details.

It is important to note that ConfigCat will add the feature flag's key to your user's identifier, which will make sure that you're not testing all the different features with the same group of users all the time.

Percentages Are Sticky

Output of the SHA1 function seems random, but is actually determined by a specific series of mathematical operations. They ensures three important things:

  • outputs are unpredictable - even a small change like turning "jane" into "Jane" will have a wildly different output, so even people with emails from the same company aren't any more likely to end up in the same group;
  • outputs are evenly distributed - any user is equally likely to end up in any of the groups, so you won't have too much data for one version and not enough for others;
  • the same input always has the same output - if the output were truly random, the same user would keep switching between groups on different devices, which would lead to a bad user experience.

The last feature of this approach ensures that the same user always has the same experience, since the described calculation method is the same across all platforms. Furthermore, this calculation can be performed as many times as necessary, e.g. on fresh installs or after cache deletion, and the result will always be the same, without the need to save or sync the result in any way.

The only way to change the experience for the user is to set your percentages differently. In our example, if you change from a 50-50 split to 70-30, Jane will suddenly see the new version (65 being less than 70). However, if you dial the percentage back to 64 and below, she'll be back on the old version.