React Native Expo Plugin

Learn to integrate Smartech SDK with your React Native Expo application.

Integrate Smartech with React Native Expo Plugin

Integrating the Smartech SDK with your React Native Expo application enables advanced features such as push notifications and in-app messaging. This document explains how to install and configure Smartech plugins for a React Native Expo Project. Follow the steps given below to integrate Smartech's features into your app, enhancing your ability to connect with users effectively.

  1. Installing Smartech React Native Plugins
    Before using the Smartech SDK in your React Native application, you must install the necessary plugins. These plugins enable core functionalities such as push notifications, app inbox, and user nudges. Follow the commands below to install each plugin.
npm install smartech-base-react-native --save

npm install smartech-push-react-native --save

npm install smartech-appinbox-react-native --save

// If you are using the Nudge feature.
npm install smartech-reactnative-nudges --save
  1. Installing Smartech React Native Expo Plugins
    After setting up the React Native plugins, the next step is to install the Smartech Expo plugins.
npm install smartech-base-expo-plugin --save

npm install smartech-push-expo-plugin --save

npm install smartech-appinbox-expo-plugin --save
  1. Configure the App.json or App.config.js File
    Once the plugins are installed, configure your Expo project to use these plugins. Depending on your project setup, modify the app.json or app.config.js file. These configuration files contain key details such as Smartech App ID, Bundle Name, and other necessary metadata.
  • Using [app.json](doc:react-native-expo-plugin#appjson): Update the app.json file with the required plugin nodes and configurations.
  • Using [app.config.js](doc:react-native-expo-plugin#appconfigjs): Update the app.config.js file accordingly.
  1. Build and Run the App
    After installing the necessary plugins and updating your configuration file, you can run the below command to delete and recreate the iOS and Android directories. This step ensures the Smartech SDK and plugins are properly integrated into your app.
  • Command to Prebuild the Project
npx expo prebuild --clean
  • For iOS, go to the iOS folder and run the command below.
pod install
  • Command to Run the App on Android
npx expo run:android
  • Command to Run the App on Android
npx expo run:ios
  1. Configure Plugin Parameters
    Configure various parameters in your project files to customize the behavior of Smartech plugins. These parameters include control logging, SDK versions, metadata, and more. Here are the parameters for smartech-base-expo-plugin, smartechNudges (Android & iOS) and deeplink handling (smartech-push-expo-plugin).
1. smartech-base-expo-plugin
ParameterDescriptionExample Value
isNewArchEnabled Indicates if the React Native New Architecture is enabled. Set to true to enable or false to disable.true
deepLinkDelay3
android.isLogEnabledEnables or disables logging for Android. Set to true to enable logging or false to disable.true
android: backupXMLFilesThis is the path of your XML files. Refer to the given link for more details.assets
android.isKotlinProjectSpecifies whether the project is using Kotlin. It is set to true if the project is in Kotlin or false otherwise.true
android.smartechMetaDataMetadata key-value pairs are used to configure Smartech on Android.[{"name": "SMT_APP_ID", "value": "06b57d52c914803e4de8cbcb978da09f"}]
ios.appIdThe Smartech App ID for iOS.3bdc168fce4668fab6aca8885cc03221
ios.bundleIdentifierThe bundle identifier for the iOS app.com.netcore.SmartechApp
ios.groupIdentifierThe group identifier for the iOS app.com.netcore.SmartechApp
ios.autoFetchLocationIt automatically fetches the device's location in iOS when it is set to true.false
ios.useAdvIDEnables the Advertising Identifier (IDFA) to be used in iOS when set to true.true
ios.isLogEnabledEnables or disables logging for iOS.true
2. smartnudges
ParameterOSDescriptionExample Value
smartechNudgesEnabled Enables or disables the Smartech Nudges feature. Set to true to enable, or false to disable.true
SMARTECH_NUDGE_VERSION (Android)Specifies the version of the Smartech Nudges SDK to be used for Android.10.2.0
isLogEnabledAndroidEnables debug logs for Smartech Nudgestrue
useEncryptionAndroidEnables encryption for Smartech Nudges in Android. Set to true to enable, or false to disable.true
addTestDeviceAndroidEnables you to add your device as a test device.true
isLogEnabledAndroidEnables or disables logging for Smartech Nudges in Android. Set to true to enable logging, or false to disable.true
smartechNudgesMetaDataAndroidAn array of metadata key-value pairs for configuring Smartech Nudges on Android.[{"name": "HANSEL_APP_ID", "value": "your-hansel-app-id"}, {"name": "HANSEL_APP_KEY", "value": "your-hansel-app-key"}]
appIdiOSThe Smartech Nudges App ID for iOS.HG7WKEM8KK3V8LVNGGDDO04D4
isLogEnablediOSEnables debug logs for Smartech Nudgestrue
addTestDeviceiOSEnables you to add your device as a test devicetrue
appKeyiOSThe Smartech Nudges App Key for iOS.XAP23PIPEI1V1BEZZE5PPZ0YSWQFN45SQTV9MO353OODNSUSU0
testDeviceURLNameiOSThe test device URL name for Hansel in iOS.com.netcore.SmartechApp
testDeviceURLSchemaiOSThe test device URL schema for Hansel in iOS.hanselpebbletrace
3. smartech-push-expo-plugin
ParameterDescriptionExample Value
android.SMARTECH_PUSH_SDK_VERSIONSpecifies the Smartech Push SDK version for Android.3.5.1
android.isKotlinProjectIndicates whether the project is using Kotlin.true
android.useSmartechFCMEnable the use of Smartech FCM on Android.true
ios.groupIdentifierGroup identifier for iOS.com.netcore.SmartechApp
ios.modeUsed to configure APNs environment entitlement.development or production
4.smartech-appinbox-expo-plugin
ParameterDescriptionRequiredExample Value
android.SMARTECH_APPINBOX_SDK_VERSIONSpecifies the Smartech AppInbox SDK version for Android.Yes3.5.1

Configuration Code Samples

Below are the essential code samples for configuring your app in App.json and app.config.js.

app.json

{
  "ios": {
    "buildNumber": "<build-number>",
    "bundleIdentifier": "<bundle-identifier>"
  },
  "android": {
    "allowBackup": true,
    "googleServicesFile": "<path-of-file>",
    "intentFilters": [
      {
        "action": "VIEW",
        "autoVerify": true,
        "data": [
          {
            "scheme": "your-scheme-for-test-device"
          }
        ],
        "category": [
          "BROWSABLE",
          "DEFAULT"
        ]
      }
    ]
  },
  "plugins": [
    [
      "smartech-base-expo-plugin",
      {
        "isNewArchEnabled": false,
        "deepLinkDelay": 3,
        "android": {
          "isLogEnabled": true,
          "SMARTECH_BASE_SDK_VERSION": "3.5.4",
          "isKotlinProject": true,
          "backupXMLFiles": "<path-of-xml-files>",
          "smartechMetaData": [
            {
              "name": "SMT_APP_ID",
              "value": "<your-smartech-app-id>"
            }
          ],
          "smartechNudges": {
            "smartechNudgesEnabled": true,
            "SMARTECH_NUDGE_VERSTION": "10.2.2",
            "useEncryption": false,
            "addTestDevice": true,
            "isLogEnabled": true,
            "smartechNudgesMetaData": [
              {
                "name": "HANSEL_APP_ID",
                "value": "<your-hansel-app-id>"
              },
              {
                "name": "HANSEL_APP_KEY",
                "value": "<your-hansel-app-key>"
              }
            ]
          }
        },
        "ios": {
          "appId": "<your-smartech-app-id>",
          "bundleIdentifier": "<your-app-bundle-id>",
          "groupIdentifier": "<your-app-group-id>",
          "autoFetchLocation": false,
          "useAdvID": false,
          "isLogEnabled": true,
          "smartechNudges": {
            "smartechNudgesEnabled": true,
            "isLogEnabled": true,
            "addTestDevice": true,
            "appId": "<your-hansel-app-id>",
            "appKey": "<your-hansel-app-key>",
            "testDeviceURLName": "<your-url-name>",
            "testDeviceURLSchema": "<your-url-schema>"
          }
        }
      }
    ],
    [
      "smartech-push-expo-plugin",
      {
        "android": {
          "SMARTECH_PUSH_SDK_VERSION": "3.5.1",
          "isKotlinProject": true,
          "useSmartechFCM": true
        },
        "ios": {
          "groupIdentifier": "<your-app-group-id>",
          "mode": "development/ production"
        }
      }
    ],
    [
      "smartech-appinbox-expo-plugin",
      {
        "android": {
          "SMARTECH_APPINBOX_SDK_VERSION": "3.5.1"
        }
      }
    ],
    "./withSmartechCustomConfig.js"
  ]
}

app.config.js

{
  "ios": {
    "buildNumber": "<build-number>",
    "bundleIdentifier": "<bundle-identifier>"
  },
  "android": {
    "allowBackup": true,
    "googleServicesFile": "<path-of-file>",
    "intentFilters": [
      {
        "action": "VIEW",
        "autoVerify": true,
        "data": [
          {
            "scheme": "your-scheme-for-test-device"
          }
        ],
        "category": [
          "BROWSABLE",
          "DEFAULT"
        ]
      }
    ]
  },
  "plugins": [
    [
      "smartech-base-expo-plugin",
      {
        "isNewArchEnabled": false,
        "deepLinkDelay": 3,
        "android": {
          "isLogEnabled": true,
          "SMARTECH_BASE_SDK_VERSION": "3.5.4",
          "isKotlinProject": true,
          "backupXMLFiles": "<path-of-xml-files>",
          "smartechMetaData": [
            {
              "name": "SMT_APP_ID",
              "value": "<your-smartech-app-id>"
            }
          ],
          "smartechNudges": {
            "smartechNudgesEnabled": true,
            "SMARTECH_NUDGE_VERSTION": "10.2.2",
            "useEncryption": false,
            "addTestDevice": true,
            "isLogEnabled": true,
            "smartechNudgesMetaData": [
              {
                "name": "HANSEL_APP_ID",
                "value": "<your-hansel-app-id>"
              },
              {
                "name": "HANSEL_APP_KEY",
                "value": "<your-hansel-app-key>"
              }
            ]
          }
        },
        "ios": {
          "appId": "<your-smartech-app-id>",
          "bundleIdentifier": "<your-app-bundle-id>",
          "groupIdentifier": "<your-app-group-id>",
          "autoFetchLocation": false,
          "useAdvID": false,
          "isLogEnabled": true,
          "smartechNudges": {
            "smartechNudgesEnabled": true,
            "isLogEnabled": true,
            "addTestDevice": true,
            "appId": "<your-hansel-app-id>",
            "appKey": "<your-hansel-app-key>",
            "testDeviceURLName": "<your-url-name>",
            "testDeviceURLSchema": "<your-url-schema>"
          }
        }
      }
    ],
    [
      "smartech-push-expo-plugin",
      {
        "android": {
          "SMARTECH_PUSH_SDK_VERSION": "3.5.1",
          "isKotlinProject": true,
          "useSmartechFCM": true
        },
        "ios": {
          "groupIdentifier": "<your-app-group-id>",
          "mode": "development/ production"
        }
      }
    ],
    [
      "smartech-appinbox-expo-plugin",
      {
        "android": {
          "SMARTECH_APPINBOX_SDK_VERSION": "3.5.1"
        }
      }
    ],
    "./withSmartechCustomConfig.js"
  ]
}

Custom Smartech Configuration

Include this custom Smartech config file in your project setup provides flexibility and simplifies maintenance. It allows you to easily modify the Firebase dependency version as requirements change, ensuring compatibility and easy updates. Additionally, you can extend functionality by adding custom code, such as location permissions or other project-specific dependencies. This approach helps keep your project adaptable and efficiently supports future enhancements.

const {
  AndroidConfig,
  withAndroidManifest,
  withAppBuildGradle,
  withDangerousMod,
  withAndroidBuildProperties,
  withInfoPlist,
  withEntitlementsPlist
} = require('expo/config-plugins');

const fs = require('fs');
const path = require('path');


// This method modifies the Android build.gradle files to include Firebase dependencies and Google Services plugin
const withFirebaseDependencyAndroid = (config) => {

  // Adds Firebase BOM (Bill of Materials) and Firebase Messaging dependencies in the app's build.gradle file.
  config = withAppBuildGradle(config, (config) => {
    if (config.modResults.language === 'groovy') {
      config.modResults.contents = config.modResults.contents.replace(
        /dependencies\s*{/,
        `dependencies {
          implementation platform('com.google.firebase:firebase-bom:33.1.2')
          implementation 'com.google.firebase:firebase-messaging'`
      );
    }
    return config;
  });

  // Ensures the 'com.google.gms.google-services' plugin is applied in the app's build.gradle file.
  config = withAppBuildGradle(config, (config) => {
    if (config.modResults.language === 'groovy') {
      // Add apply plugin statement for Google Services
      if (!config.modResults.contents.includes("apply plugin: 'com.google.gms.google-services'")) {
        config.modResults.contents += `apply plugin: 'com.google.gms.google-services'`;
      }
    }
    return config;
  });


  // Adds the classpath for Google Services in the root build.gradle file (Project level).
  config = withDangerousMod(config, [
    'android',
    async (config) => {
      const gradleFilePath = path.join(config.modRequest.projectRoot, 'android', 'build.gradle');
      let gradleFileContents = await fs.promises.readFile(gradleFilePath, 'utf8');

      // Add classpath for Google Services plugin if it's not already present
      if (!gradleFileContents.includes("classpath 'com.google.gms:google-services:4.4.2'")) {
        gradleFileContents = gradleFileContents.replace(
          /dependencies\s*{/,
          `dependencies {
          classpath 'com.google.gms:google-services:4.4.2'`
        );
        await fs.promises.writeFile(gradleFilePath, gradleFileContents, 'utf8');
      }

      return config;
    },
  ]);


  return config;
}

// Android: Config plugin to add location permissions (foreground and background) to the AndroidManifest.xml
const withLocationPermissionsAndroid = (config) => {
  return withAndroidManifest(config, async (config) => {
    const manifest = config.modResults;

    // List of location permissions for Android (fine and coarse location)
    const locationPermissions = [
      'android.permission.ACCESS_FINE_LOCATION',
      'android.permission.ACCESS_COARSE_LOCATION',
    ];

    const backgroundLocationPermission = 'android.permission.ACCESS_BACKGROUND_LOCATION';

    // Ensure the permissions are added
    for (const permission of locationPermissions) {
      if (!hasPermission(manifest, permission)) {
        manifest.manifest['uses-permission'] = [
          ...(manifest.manifest['uses-permission'] || []),
          { $: { 'android:name': permission } },
        ];
      }
    }

    // Add ACCESS_BACKGROUND_LOCATION permission for Android 10+
    if (!hasPermission(manifest, backgroundLocationPermission)) {
      manifest.manifest['uses-permission'] = [
        ...(manifest.manifest['uses-permission'] || []),
        { $: { 'android:name': backgroundLocationPermission } },
      ];
    }

    return config;
  });
};

// Helper function to check if permission is already added
function hasPermission(manifest, permission) {
  return manifest.manifest['uses-permission']?.some(
    (perm) => perm.$['android:name'] === permission
  );
}


// Config plugin to add background location permissions and enable background modes in Info.plist
const withBackgroundLocationIos = (config) => {
  // Modify Info.plist to include location permission descriptions and enable background location mode
  config = withInfoPlist(config, (config) => {
    // Add or update the description for requesting permission to always use the user's location
    config.modResults.NSLocationAlwaysUsageDescription =
      'We use your location to track your movements in the background.';

    // Add or update the description for requesting permission to use the user's location only while the app is in use
    config.modResults.NSLocationWhenInUseUsageDescription =
      'We use your location to track your movements while the app is open.';

    // Enable background location mode by adding 'location' to the UIBackgroundModes array
    config.modResults.UIBackgroundModes = [
      ...(config.modResults.UIBackgroundModes || []), // Ensure the array exists or create one
      'location', // Add 'location' to enable background location services
    ];
    return config;
  });

  // Modify the iOS Entitlements.plist to allow background location usage
  config = withEntitlementsPlist(config, (config) => {
    // Modify the 'com.apple.security.application-groups' entitlement to include 'location'
    config.modResults['com.apple.security.application-groups'] = [
      ...(config.modResults['com.apple.security.application-groups'] || []),
      'location',
    ];
    return config;
  });

  return config;
};


// Custom configuration function for modifying the Expo app's configuration
const withSmartechCustomConfig = (config) => {

  // Add Firebase dependency for Android
  config = withFirebaseDependencyAndroid(config);

  // Add location permissions for Android
  //config = withLocationPermissionsAndroid(config);


  return config;
};

module.exports = withSmartechCustomConfig;

Retrieving Deeplink Data

The method below provides the deep link value and the custom payload when a push notification is clicked.

Use this code when your smartech-base-react-native version is 3.5.0 or above, & smartech-push-react-native version is 3.5.0 or above.

import SmartechReact from 'smartech-base-react-native';
import SmartechPushReact from 'smartech-push-react-native';

// Deeplink callback for Push Notification, InappMessage and AppInbox
 SmartechReact.addListener(SmartechReact.SmartechDeeplink, handleDeeplinkWithPayload);

const handleDeeplinkWithPayload = (smartechData) => {
     console.log('Smartech Data :: ', smartechData);
     console.log('Smartech Deeplink :: ', smartechData.smtDeeplink);
     console.log('Smartech CustomPayload:: ', smartechData.smtCustomPayload);
  };

//Remove this listener on cleanup
SmartechReact.removeListener(SmartechReact.SmartechDeeplink);

Tracking the Re-Installs (only for Android)

Step 1: Create the full backup content file.

Create a backup.xml file in your project directory. Copy the below snippet in your XML file.

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <include domain="sharedpref" path="smt_guid_preferences.xml"/>
    <include domain="sharedpref" path="smt_preferences_guid.xml"/>
</full-backup-content>

Android 12 or higher

If your app targets Android 12 (API level 31) or higher, create an XML file backup_31.xml in your project. Copy the below snippet in your XML file.

<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
   <cloud-backup disableIfNoEncryptionCapabilities="false">
       <include  domain="sharedpref" path="smt_guid_preferences.xml" />
       <include domain="sharedpref" path="smt_preferences_guid.xml" />
   </cloud-backup>
</data-extraction-rules>

Refer to the links below to learn more about the React Native SDK.

User & Event Tracking

Product Experience

App Inbox Integration