Expo Guide

If you are using expo for building React Native guide, The android setup is little bit different, Please follow the guide below

VWO Insights on Expo

Use this with an Expo app that includes native code (a development build or an EAS build). Expo Go cannot load this SDK.

The React Native CLI setup still applies on iOS. Android in an Expo app needs the config plugin below. Do not paste the init call into MainApplication by hand.

Why a plugin is required

On Android, the SDK has to start in Application.onCreate, before React Native creates a window. config() from JavaScript does that on iOS only. On Android it returns null and does not initialize the SDK.

An Expo project does not treat android/ as source you edit. Native files are generated by npx expo prebuild (Continuous Native Generation). A config plugin is the supported way to change those generated files. The plugin runs during prebuild and writes the init into MainApplication.

Two consequences:

  • npx expo start and a reload do not run the plugin. If android/ already exists, npx expo run:android does not run it either. Run prebuild when you add or change the plugin.
  • Editing android/ yourself is overwritten the next time prebuild runs. Keep the init in the plugin.

iOS does not need this plugin. Call config() from JavaScript.

1. Install the SDK

npx expo install vwo-insights-react-native-sdk

Use npx expo install, not npm install, so the version stays compatible with the Expo SDK.

2. Add the plugin

Create plugins/withVwoAndroidInit.js:

const { withMainApplication } = require('expo/config-plugins');

function withVwoAndroidInit(config, { accountId, sdkKey, userId = '' } = {}) {
  if (!accountId || !sdkKey) {
    throw new Error('Pass accountId and sdkKey to withVwoAndroidInit.');
  }

  return withMainApplication(config, (config) => {
    const semi = config.modResults.language === 'kt' ? '' : ';';
    let src = config.modResults.contents;

    const importLine = `import com.vwo.insights.events.VWOLog${semi}\nimport com.vwoinsightsreactnativesdk.VwoInsightsReactNativeSdkModule${semi}`;
    if (!src.includes('import com.vwoinsightsreactnativesdk.VwoInsightsReactNativeSdkModule')) {
      src = src.replace(
        /import com\.facebook\.react\.ReactApplication;?/,
        (match) => `${match}\n${importLine}`
      );
    } else if (!src.includes('import com.vwo.insights.events.VWOLog')) {
      src = src.replace(
        /import com\.vwoinsightsreactnativesdk\.VwoInsightsReactNativeSdkModule;?/,
        (match) => `import com.vwo.insights.events.VWOLog${semi}\n${match}`
      );
    }

    const logLine = `    VWOLog.setLogLevel(VWOLog.ALL)${semi}`;
    const initLine = `    VwoInsightsReactNativeSdkModule.init(this, "${accountId}", "${sdkKey}", "$USERID")${semi}`;
    if (!src.includes('VwoInsightsReactNativeSdkModule.init')) {
      src = src.replace(
        /super\.onCreate\(\);?/,
        `super.onCreate()${semi}\n${logLine}\n${initLine}`
      );
    } else if (!src.includes('VWOLog.setLogLevel')) {
      src = src.replace(
        /(\s*)VwoInsightsReactNativeSdkModule\.init/,
        `${logLine}\n$1VwoInsightsReactNativeSdkModule.init`
      );
    }

    config.modResults.contents = src;
    return config;
  });
}

module.exports = withVwoAndroidInit;

The plugin file has no credentials. Each app passes its own values.

Register it in app.json or app.config.js:

{
  "expo": {
    "plugins": [
      [
        "./plugins/withVwoAndroidInit",
        {
          "accountId": "YOUR_ACCOUNT_ID",
          "sdkKey": "YOUR_SDK_KEY",
          "userId": ""
        }
      ]
    ]
  }
}

userId is optional. Leave it empty when the visitor is anonymous, or pass a stable id when you know the user.

3. Generate the native project and build

npx expo prebuild --platform android
npx expo run:android

Prebuild writes VWOLog.setLogLevel(VWOLog.ALL) and VwoInsightsReactNativeSdkModule.init(...) into MainApplication.onCreate, immediately after super.onCreate().

Checklist

  • Plugin is listed in app.json with accountId and sdkKey.
  • npx expo prebuild has been run after adding the plugin.
  • The app is a development build or an EAS build, not Expo Go.
  • config() and startRecording() run from JavaScript.
  • Screen names do not start with / or ./.