Skip to content

React Native Usage

This page explains how to use Context Decision to calibrate your custom model, and how to make decisions based on the predictions

  • Step 1: Add ContextSDK to your app
  • Step 2: Ship app into production in Calibration Mode
  • Step 3: Once the model is ready, you can start making decisions based on the SDK's predictions

Usage

  • Use a different, unique flowName for each upsell funnel (e.g. upsell_prompt, upsell_onboarding, etc.)
    • If you have the same purchase flow, but from different parts of your app, please use different a different flowName for each.
    • We automatically analyze the overlap between different flows, to decide if there should be one, or more models.
  • The timing is crucial: You need to create the context object right before showing your prompt, and then log the outcome of the user interaction after the user has either accepted or dismissed the prompt.
  • For each context object you create, be sure to log an outcome, even if the user dismisses the prompt.

In most cases, ContextSDK will execute your callback instantly. Only if your app was recently launched, or resumed from the background, it will take up to a few seconds to get a full context.

import { optimize } from 'react-native-context-sdk';
import { Outcome } from 'react-native-context-sdk/lib/typescript/src/context';

optimize({
    flowName: 'upsell',
    onGoodMoment: async (context) => {
        // Show the upgrade prompt here right after fetching the context
        // Once you know if the user purchased or dismissed the upsell, log the outcome:
        context.log(Outcome.positive); // or Outcome.negative
    },
});

It's critical you trigger your prompt inside the callback, which behaves as follows:

  • The callback is instantly executed if your app has been running for at least 3 seconds
  • The callback being executed within 3 seconds if your app was just put into the foreground recently

This way, ContextSDK guarantees to always have a full context ready, therefore increasing its accuracy in those cases.

There are cases where you may prefer to always instantly have your callback executed. For example, when you want to show a prompt right after a certain user-action, to prevent the prompt showing up when the user already left the screen.

import { optimize } from 'react-native-context-sdk';
import { Outcome } from 'react-native-context-sdk/lib/typescript/src/context';

optimize({
    flowName: 'upsell',
    maxDelay: 0,
    onGoodMoment: async (context) => {
        // Setting maxDelay to 0 causes the callback to be called immediately.

        if (await context.shouldUpsell()) {
          // Show the upgrade prompt here right after fetching the context
          // Once you know if the user purchased or dismissed the upsell, log the outcome:
          await context.log(Outcome.positive); // or Outcome.negative
        } else {
          // Don't do anything - it's a bad moment.
          // Make sure to still log a Skipped outcome so we get the full picture.
          await context.log(Outcome.skipped);
        }
    }
});

You can also use ContextSDK with a simple imperative syntax, if using callbacks is undesireable or would make your code harder to write:

import { instantContext } from 'react-native-context-sdk';
import { Outcome } from 'react-native-context-sdk/lib/typescript/src/context';

const context = await instantContext({
    flowName: 'upsell'
});
if (await context.shouldUpsell()) {
    // Show your upsell prompt here.
    await context.log(Outcome.positive); // or Outcome.negative
} else {
    // Don't do anything - it's a bad moment.
    // Make sure to still log a Skipped outcome so we get the full picture.
    await context.log(Outcome.skipped);
}

The main thing to note here is that you are fully responsible for making sure that the result of Context.shouldUpsell is handled, and to call context.log(Outcome.Skipped); in the case where Context.shouldUpsell == false.

Also note that instantContext will not return a full context object if called shortly after the app was opened. This is not an issue as long as the majority of calls to it happen after the apps has been running for a bit already.

Helpers

Some apps may not have an easy way to pass the context object from where you initially generate it, to where you know the outcome of the user interaction. In those cases, you can use the recentContext method to get the most recent context object based on the unique flowName. recentContext can be used with context objects created by the optimize, and instantContext methods.

Important: This approach requires you to create the context object first using either optimize, or instantContext. Only the most recent context for each flowName name will be stored, and older context objects will be discarded.

The context must already be created at the time the prompt is shown. recentContext only allows you to log the outcome of the user interaction together with the context object from the moment right before the prompt was shown.

optimize({
    flowName: 'upsell',
    onGoodMoment: async (context) => {
        // [Prompt the user for an upgrade right after getting the context]
    }
});
// Once the user either finished the purchase, or dismissed the upgrade:
const outcome = Outcome.Positive; // or .negative

const context = await recentContext("upsell");
if (context) {
    await context.log(outcome);
}

Custom Signals

ContextSDK uses more than 170 signals based on various built-in sensors to make its predictions. However, you can improve its performance by providing additional data to the ContextSDK that's specific to your app. Some examples of what you could provide: In-game progress, number of friends/messages, number of entries in a list, etc.

If you have custom signals that are relevant for all of your flows, you can declare them globally, and they will be automatically added to every context object you fetch.

setGlobalCustomSignals({ user_has_premium_subscription: true })

You can easily override the global custom signals by providing the same id when calling the setGlobalCustomSignal method again using a different value. To remove a global custom signal, simply call the setGlobalCustomSignal method with a null value.

In general, we recommend using global signals. But if have custom signals that are specific to a certain flow, you can provide them as a parameter when getting your context object:

optimize({
    flowName: 'test_flow_calibrate',
    maxDelay: 0,
    onGoodMoment: async (context) => {
      // ...
    },
    customSignals: {
        percentage_onboarding_finished: 0.3,
        upsell_copy_button_used: "Purchase Premium",
        number_of_friends: 4
    }
  });

Custom Model Rollout

Once you've shipped your app with ContextSDK in calibration mode to the App Store, and you've collected around 1,000 sales events, we can start training your custom machine learning model to optimize your app.

Your custom model is trained on your app's data and is unique to your app. This ensures that the model performs the best for your app, and your user-base.

Our recommended approach is to distribute your machine learning models over-the-air directly to your app. This works instantly, uses minimal system resources in the background, and allows us to iterate faster and more efficiently to further improve your app's performance.

In the future, you'll be able to launch your first custom model on our Dashboard, but for the time being, we will reach out to you via email once your first model is ready.

If you're using optimize, no code changes are required.

  • If ContextSDK believes it's currently a good moment to show the prompt, it will run your block
  • If ContextSDK believes it's currently a bad moment to show the prompt, it will not run your block

If you're using the advanced usage using instantContext, you'll need to check .shouldUpsell yourself to decide if you should show the prompt or not.

Our OTA rollouts are safe, reliable, and won't affect your app's performance. Our systems continuously monitor the rollout and the resulting conversion performance to ensure everything is working as expected.

If you prefer to disable Over-the-Air updates, we can provide you with a custom SDK binary that includes your custom model. Please drop us a short email at support@contextsdk.com containing your installation method (CocoaPods, SPM, or manual), and we will get you started.

Done with the integration? Header over to the Release Section to go live with your app!