npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

smartpush-sdk-react

v3.0.0

Published

Pluggable's Smartpush for React Native apps

Downloads

102

Readme

Pluggable's Smartpush Plugin for React Native apps

A React Native plugin for React Native apps.

Pre-conditions [Integrate with FCM]

Before using this plugin you should guarantee that your app already integrates with React Native Firebase and then with Firebase Cloud Messaging (FCM). The steps are quite easy to follow.

  1. Create a new Firebase project. Note that current versions of firebase-ios-sdk have a minimum Xcode requirement of 14.1, which implies a minimum macOS version of 12.5 (macOS Monterey);

  2. Install the React Native Firebase "app" module to the root of the React Native project with NPM: npm install --save @react-native-firebase/app. The @react-native-firebase/app module must be installed before using any other Firebase service;

  3. Android Setup - a configuration file must be downloaded and added to the project:

  • On the Firebase console, add a new Android application and enter the projects details. The "Android package name" must match the local projects package name which can be found inside of the manifest tag within the /android/app/src/main/AndroidManifest.xml file within the project;
  • Download the google-services.json file and place it inside of the project at the following location: /android/app/google-services.json;
  • To allow Firebase on Android to use the credentials, the google-services plugin must be enabled on the project. This requires modification to two files in the Android directory. First, add the google-services plugin as a dependency inside of the /android/build.gradle file:
buildscript {
  dependencies {
    // ... other dependencies
    classpath 'com.google.gms:google-services:4.3.15'
  }
}
  • Lastly, execute the plugin by adding the following to the /android/app/build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services' // <- Add this line 
  1. iOS Setup - to allow the iOS app to securely connect to the Firebase project, a configuration file must be downloaded and added to the project, and you must enable frameworks in CocoaPods:
  • On the Firebase console, add a new iOS application and enter your projects details. The "Apple bundle ID" must match your local project bundle ID. The bundle ID can be found within the "General" tab when opening the project with Xcode;
  • Download the GoogleService-Info.plist file;
  • Using Xcode, open the projects /ios/{projectName}.xcodeproj file (or /ios/{projectName}.xcworkspace if using Pods) and right click on the project name and "Add files" to the project. Select the downloaded GoogleService-Info.plist file from your computer, and ensure the Copy items if needed checkbox is enabled;
  • To allow Firebase on iOS to use the credentials, the Firebase iOS SDK must be configured during the bootstrap phase of your application. To do this, open your /ios/{projectName}/AppDelegate.mm file (or AppDelegate.m if on older react-native), and add the following:
#import "AppDelegate.h"
#import <Firebase.h> // <- Add this line
// ...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Add me --- \/
  [FIRApp configure]; // <- Add this line
  // Add me --- /\
  // ...
}
// ...
  • Beginning with firebase-ios-sdk v9+ (react-native-firebase v15+) you must tell CocoaPods to use frameworks. Open the file ./ios/Podfile and add the following line inside your targets (right after the line calling the react native Podfile function to get the native modules config):
target 'reactnativeapp' do
  config = use_native_modules!
  use_frameworks! :linkage => :static # <- Add this line
  $RNFirebaseAsStaticFramework = true # <- Add this line (see next point)
  ...
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable the next line.
  #:flipper_configuration => flipper_config, # <- COMMENT this line
  ...
  • To use Static Frameworks on iOS, you also need to manually enable this for the project with the following global to your ./ios/Podfile file:
# right after `use_frameworks! :linkage => :static`
$RNFirebaseAsStaticFramework = true
  1. Once the above steps have been completed, the React Native Firebase library must be linked to the project and the application needs to be rebuilt. Users on React Native 0.60+ automatically have access to "autolinking", requiring no further manual installation steps. To automatically link the package, rebuild your project (for manual linking, if you're using an older version of React Native without autolinking support, or wish to integrate into an existing project, you can follow the manual installation steps for iOS and Android):
# Android apps
npm run android

# iOS apps
cd ios/
pod install --repo-update
cd ..
npm run ios
  1. You can now install the messaging module by running:
# Install the messaging module
npm install @react-native-firebase/messaging

# If you're developing your app using iOS, run this command
cd ios/ && pod install

cd ..
npm run ios
  1. iOS Setup - iOS requires further configuration before you can start receiving and sending messages through Firebase. Read the documentation and follow the steps on how to setup iOS with Firebase Cloud Messaging.

NOTE: FCM via APNs does not work on iOS Simulators. To receive messages & notifications a real device is required. The same is recommended for Android. Also, for iOS, React-Native-Firebase uses use_frameworks, which has compatibility issues with Flipper, Hermes, and Fabric.

Smartpush Usage

After configuring your app to integrate with FCM, you are ready to use this plugin to properly engage with your users. To install the plugin just:

  1. First install the Smartpush Package by running npm install smartpush-sdk-react in the root of the project;

  2. Once the above steps have been completed, the React Native Firebase library must be linked to your project and your application needs to be rebuilt. Users on React Native 0.60+ automatically have access to "autolinking", requiring no further manual installation steps. To automatically link the package, rebuild your project:

# Android apps
npm run android

# iOS apps
cd ios/
pod install --repo-update
  1. OPTIONAL: For iOS, if you want to display push notifications while your app is in the foreground, you must allow that specific scenario:
  • In your app's AppDelegate.h file:
// Import the native iOS UserNotifications package
#import <UserNotifications/UserNotifications.h> // <- Add this line

// Extend the UNUserNotificationCenterDelegate class
@interface AppDelegate : RCTAppDelegate<UNUserNotificationCenterDelegate> // <- Update this line
  • In your app's AppDelegate.mm file:
// Import the native iOS UserNotifications package
#import <UserNotifications/UserNotifications.h> // <- Add this line

// ...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // ...
    [UNUserNotificationCenter currentNotificationCenter].delegate = self; // <- Add this line
    // ...
}

// ...

// Function to implement to display foreground push notifications
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
    completionHandler(UNNotificationPresentationOptionAlert|UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound);
}
  1. NOTE that for Android, to customize the used notification icon just add the desired icon in the Android's drawble folder and name it ic_push_app_icon. Otherwise, a default icon, not related to your app, will be used.

  2. Finally, this library exposes three mandatory methods, which can be imported and used like this in, for example, your App.tsx file:

...
import { 
    pluggableInitialize,
    pluggableExecute, 
    pluggableStoreFeedback
 } from 'smartpush-sdk-react';
...
  • The pluggableInitialize method is used to initialize the Smartpush plugin and should be called as soon as possible in your app's loading process, when the fcm token of the user is available:
    const COMPANY_NAME = 'your_company_name'
    const COMPANY_LICENSE = 'your_company_key'
    const FCM_TOKEN = 'the_fcm_token'
    const EXTERNAL_USER_ID = 'your_user_id'
    const EXTERNAL_TOKEN_ID = 'the_id_of_the_device'
    const EXTERNAL_USER_EMAIL = '[email protected]'
    const PLUGGABLE_LOG = true

    pluggableInitialize(
        COMPANY_NAME, 
        COMPANY_LICENSE, 
        FCM_TOKEN, 
        EXTERNAL_USER_ID, 
        EXTERNAL_TOKEN_ID, 
        EXTERNAL_USER_EMAIL, 
        PLUGGABLE_LOG
    ).then(result => {
        console.log('[RESULT]: ', result);
    });
  • The pluggableExecute method is used to deliver the notification to the user. It autonomously executes the artificial intelligence models that deliveres the notification when the user is engaged. This method also returns a Push UUID that you can store and map with your users:
// Register background handler
const PLUGGABLE_LOG = true;
messaging().setBackgroundMessageHandler(async remoteMessage => {
    const notifData = remoteMessage.data as {[key: string]: string};
    pluggableExecute(notifData, PLUGGABLE_LOG).then(pushUUID => {
        console.log('[UUID]: ', pushUUID);
        // Save the pushUUID and (your) userID to your database if you want to create mapping records
        // ...
    });
});
// Register foreground handler
function App(): JSX.Element {
    ...
    // To listen to messages in the foreground, call the onMessage method inside your application code. 
    useEffect(() => {
        messaging().onMessage(async remoteMessage => {
            const notifData = remoteMessage.data as {[key: string]: string};
            pluggableExecute(notifData, PLUGGABLE_LOG).then(pushUUID => {
                console.log('[UUID]: ', pushUUID);
                // Save the pushUUID and (your) userID to your database if you want to create mapping records
                // ...
            });
        });
    }, []);
    ...
}
  • The pluggableStoreFeedback (for remote notifications) and the pluggableClickFeedback (for non-remote notifications) methods are used to create engagement metrics, being called every time a notification is clicked. In addition, all extras sent in this notification (for deep linking, for example) are availabe in the remoteMessage.data dictionary:
// When a non-remote push is clicked
React.useEffect(() => {
    pluggableClickFeedback(event => {
        console.log('Feedback received!');
        // Handle the event, if required - it will open your main view.
    })
})

// When a remote push is clicked
function App(): JSX.Element {
    ...
    useEffect(() => {
        // When the application is opened from a quit state, check whether an initial notification is available:
        messaging().getInitialNotification().then(remoteMessage => {
            if (remoteMessage) {
                console.log('CLICKED NOTIFICATION:', remoteMessage.notification);
                const notifData = remoteMessage.data as {[key: string]: string};
                pluggableStoreFeedback(notifData, PLUGGABLE_LOG);
            }
        });
        // When the application is running, but in the background:
        messaging().onNotificationOpenedApp(remoteMessage => {
            console.log('CLICKED NOTIFICATION:', remoteMessage.notification);
            const notifData = remoteMessage.data as {[key: string]: string};
            pluggableStoreFeedback(notifData, PLUGGABLE_LOG);
        });
    }, []);
    ...
}
  • For iOS there is the need to open your /ios/{projectName}/AppDelegate.mm file (or AppDelegate.m if on older react-native), and add the following:
// Import the Smartpush Plugin
#import <smartpush_sdk_react-Swift.h> // <- Add this line

// ...

// Add this method, or the lines below, of method already implemented.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
    // Notification data
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    [SmartpushSdkReact iosStoreFeedbackWithNotificationData:userInfo log:true];
    // Returning the preferred presentation option
    completionHandler();
}
  1. Three additional methods are exposed by the library to handle tags (aka segments) subscriptions and can be used, if needed, as follows:
...
import { 
    pluggableSubscribeTag, 
    pluggableUnsubscribeTag, 
    pluggableGetSubscribedTags
 } from 'smartpush-sdk-react';
...
  • You can subscribe your client's app to a particular tag - the client will then receive notifications that are sent to that particular tag. You should call the pluggableSubscribeTag method to let the SDK subscribe the user to that tag. This returns 1, if success, otherwise an error message. For that, you must do as follows:
const TAG_NAME = 'tag_name'
const TAG_VALUE = 'tag_value'
const EXTERNAL_USER_ID = 'your_user_id'
const EXTERNAL_TOKEN_ID = 'the_id_of_the_device'
const PLUGGABLE_LOG = true

pluggableSubscribeTag(TAG_NAME, TAG_VALUE, EXTERNAL_USER_ID, EXTERNAL_TOKEN_ID, PLUGGABLE_LOG).then(result => {
    console.log('[RESULT]: ', result);
});
  • You can also unsubscribe your client's app from a particular tag. You should call the pluggableUnsubscribeTag method to let the SDK unsubscribe the user from that tag. This returns 1, if success, otherwise an error message. For that, you must do as follows:
pluggableUnsubscribeTag(TAG_NAME, EXTERNAL_USER_ID, EXTERNAL_TOKEN_ID, PLUGGABLE_LOG).then(result => {
    console.log('[RESULT]: ', result);
});
  • To get the list of tags the user is currently subscribed to you should call the pluggableGetSubscribedTags method. This returns an array of strings. For that, you must do as follows:
pluggableGetSubscribedTags(EXTERNAL_USER_ID, EXTERNAL_TOKEN_ID, PLUGGABLE_LOG).then(resultArray => {
    console.log('[RESULT]: ', resultArray);
});
  • To know the FCM registration token associated with each device, you need to implement the following:
// Main call and Get user token 
async function onAppBootstrap() {
    // Get the device token
    messaging().getToken().then(token => {
        console.log('TOKEN is:', token);
        pluggableInitialize(
            COMPANY_NAME, 
            COMPANY_LICENSE, 
            token, 
            EXTERNAL_USER_ID, 
            EXTERNAL_TOKEN_ID, 
            EXTERNAL_USER_EMAIL, 
            PLUGGABLE_LOG
        ).then(result => {
            console.log('[RESULT]: ', result);
        });
        // Store the FCM registration token in our app server
        
    });
    // Listen to whether the token changes
    messaging().onTokenRefresh(token => {
        console.log('TOKEN refreshed to:', token);
        pluggableInitialize(
            COMPANY_NAME, 
            COMPANY_LICENSE, 
            token, 
            EXTERNAL_USER_ID, 
            EXTERNAL_TOKEN_ID, 
            EXTERNAL_USER_EMAIL, 
            PLUGGABLE_LOG
        ).then(result => {
            console.log('[RESULT]: ', result);
        });
        // Store the FCM registration token in our app server
    });
}
  1. Three additional methods are exposed by the library to handle internal permissions (you are still required to ask the user for PUSH NOTIFICATION permission) and can be used, if needed, as follows:
...
import {PermissionsAndroid} from 'react-native';
import { 
    pluggableEnableInternalPushPermission,
    pluggableDisableInternalPushPermission,
    pluggableGetPushPermissionState
 } from 'smartpush-sdk-react';
...
  • To ask for the OS permission, you can do as follows:
const requestPushPermission = async () => {
    try {
        // Request PUSH permission iOS
        const authStatus = await messaging().requestPermission();
        const enabled =
            authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
            authStatus === messaging.AuthorizationStatus.PROVISIONAL;
        if(enabled){
            console.log('Authorization status:', authStatus);
        }
        // Request PUSH permission ANDROID
        const granted = await PermissionsAndroid.request(
            PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS,
            {
                title: 'Cool push notifications?',
                message:
                    'Do you want to receive ' +
                    'cool push notifications with lots of promotions?',
                buttonNeutral: 'Ask Me Later',
                buttonNegative: 'Cancel',
                buttonPositive: 'OK',
            },
        );
        if (granted === PermissionsAndroid.RESULTS.GRANTED) {
            console.log('You can use pushes.');
        } else {
            console.log('Push permission denied');
        }
    } catch (err) {
        console.warn(err)
    }
}
  • Finally, the three additional methods that allows you to internally enable/disable push notifications (without disabling the OS permission itself) are the pluggableEnableInternalPushPermission, pluggableDisableInternalPushPermission, and pluggableGetPushPermissionState. These methods return 0, if the push permissions is disabled, 1, if the push permission is enabled, and -1, meaning that the user did not grant the required OS permission for push notifications. You can use these as follows:
const PLUGGABLE_LOG = true
pluggableEnableInternalPushPermission(PLUGGABLE_LOG).then(result => {
    console.log('[RESULT]: ', result);
});

pluggableDisableInternalPushPermission(PLUGGABLE_LOG).then(result => {
    console.log('[RESULT]: ', result);
});

pluggableGetPushPermissionState(PLUGGABLE_LOG).then(result => {
    console.log('[RESULT]: ', result);
});

More info

  • For full compatibility, attention to the used versions of XCODE, SWIFT and COCOAPODS. Recommended versions are XCODE=15, SWIFT=5.9, and COCOAPODS=1.14.2.

  • For more info visit https://pluggableai.xyz/ or give us feedback to [email protected].