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

react-native-quantum-metric-library

v3.0.10

Published

Quantum Metric module for React Native

Downloads

13,274

Readme

Quantum Metric React Native Module

This module is only for React Native apps and requires an account with Quantum Metric.

Note: You must first have already installed our Native SDKs before installing this module

What is this?

This module includes some extra features that improve our React Native capture support. You must have installed our Native SDKs on both iOS/Android before this native module can do anything. This module depends on having the native SDK already in the app.

Please refer to the platform-specific integration instructions located here -

iOS: https://community.quantummetric.com/s/article/iOS-SDK-Integration-Instructions Android: https://community.quantummetric.com/s/article/Android-Integration-Instructions

What is this used for?

  1. Adds support for Pages within Quantum. Navigation information is stored on the javascript side of react native, so in order to know the user moved to a new part of your app, we can do this with the Page Syncing with React Navigation integration (section below).
  2. Gives you full control over masking/encryption. Using the QuantumComponent (described below), you can let Quantum know which pieces of text displayed in your app should be masked (replaced with *** in replay) or encrypted (so that only the bearer of the private key on your team can decrypt and view that text).
  3. Capturing network requests on Android. Depending on what version of react native you are using, we will automatically detect if we need to use this Module to grab network information that is not possible to grab from the native SDK.

Install React Native Module

First use npm (or yarn) to install this library.

npm install react-native-quantum-metric-library

Next import the library into the app component:

import { QuantumMetricLibrary } from 'react-native-quantum-metric-library';

Initialization

To initialize the library and get a session started, you have a number of options. The library MUST be initialized either from the javascript side OR from the native side.

Initializing directly from the javascript/typescript side

Initialization from the JS side can be achieved with one of two related functions:

function initialize (subscription: string, uid: string) function initializeWithOptions(subscription: string, uid: string, options: {})

In each of these, the subscription and uid strings should be those provided by your QM contact. With the second function, the following options are available:

testModeEnabled: true/false
sslPinningEnabled: true/false
crashReportingEnabled: true/false

testModeEnabled will dictate whether production configuration or test configuration should be used. Using test mode can be helpful if you want to use different config in a development environment. sslPinningEnabled enables SSL certificate pinning for requests to Quantum Metric's servers. Please contact us if you'd like to enable this. (If you do enable it, you'll need to deploy a new build of the library when we get new SSL certificates) crashReportingEnabled will dictate whether QM will set itself as your app's crash handler. If you want to enable this, check with your QM team to make sure crash reporting is configured properly.

Calling either of these functions will initialize the Quantum Metric SDKs, both iOS and Android. We recommend calling these functions near the beginning of the app lifecycle to begin capture as soon as possible, such as in the componentDidMount() of the App component, like so:

componentDidMount() {
  QuantumMetricLibrary.initialize(<subscription>, <uid>);
}

Initializing from the native side

If you wish to initialize session capture from the native side, a little bit of JS work is still required. Add the following into the componentDidMount() of the App component:

componentDidMount() {
  QuantumMetricLibrary.init();
}

In addition to this, follow the initialization instructions detailed in the platform-specific integration guides:

iOS: https://community.quantummetric.com/s/article/iOS-SDK-Integration-Instructions Android: https://community.quantummetric.com/s/article/Android-Integration-Instructions

Masking and Encrypting Text in Components

As of version 3.0.0, this module includes a component you can use to wrap your components in, in order to mark them as needing masking/encryption.

Let's say you have a component that looks like this:

<Text>Your name:</Text>
<Text>First Last</Text>
<Text>Your address:</Text>
<Text>123 Address Street</Text>

You can wrap the Text components with a QuantumComponent, and pass in privacy parameters, for example:

<Text>Your name:</Text>
<QuantumComponent privacy="encrypt">
  <Text>First Last</Text>
</QuantumComponent>
<Text>Your address:</Text>
<QuantumComponent privacy="mask">
  <Text>123 Address Street</Text>
</QuantumComponent>

When this part of your app is captured, Quantum will send off an encrypted version of the name, and a masked version of the address. The address will never be sent to Quantum's servers.

Masking using this method has better performance that Quantum's remote masking capabilities, and gives you full control over user privacy.

Don't forget to import the component at the top of the file you're using it in:

import {QuantumMetricLibrary, QuantumComponent} from 'react-native-quantum-metric-library';

Unmasking Text in Components

As of version 3.0.6 of this package, you can pass in a privacy filter of "unmask" to indicate that a view should not be masked. Please note that this requires the following versions of our native SDKs:

Android: 1.0.18 iOS: 1.1.11

This functionality is useful if you want to mark a view (and its subviews) as NOT containing any PII. For example, if your subscription has been figured with "mask everything mode", you can use this to mark views as safe for displaying their contents.

Using the example from above, suppose you have these components

<Text>Your name:</Text>
<Text>First Last</Text>
<Text>Your address:</Text>
<Text>123 Address Street</Text>

and your subscription has been set to mask-everything mode, such that all views are automatically masked. You can then specify that certain components do NOT need to be masked, like so:

<QuantumComponent privacy="unmask">
  <Text>Your name:</Text>
</QuantumComponent>
<Text>First Last</Text>
<QuantumComponent privacy="unmask">
  <Text>Your address:</Text>
</QuantumComponent>
<Text>123 Address Street</Text>

Page Syncing with React Navigation

Since React Native apps do not use Activities or View Controllers under the hood, we need to rely on the Javascript side to tell us when a "page" happens on the native side. This module includes the QuantumMetricLibrary.sendNewPageNamed() function you can use to tell Quantum when a new page appeared.

React Navigation is one of the most common libraries used for navigation, so we'll show you one possible example integration here.

The render() function of your main App component might look something like this:

render() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
        <Stack.Screen name="DeeperDetails" component={DeeperDetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

The main idea is that we'll use onStateChange in the NavigationContainer to see when the route changes (which means the user navigated somewhere), and tell Quantum that the route changed, and pass in the new page name. The react docs refer to this as Screen Tracking, our implementation is similar to their example. If you have a Function component for your main App component, you can follow their example here, but most likely you have a Class component.

1. Create References

First we'll need to create references to the navigation container and route name, so we can see if it changed. In your constructor create these refs:

constructor(props) {
  super(props);

  this.navigationRef = React.createRef();
  this.routeNameRef = React.createRef();
}

2. Use onRead and onStateChange listeners

Next, we'll setup the ref to the NavigationContainer, and use the onReady and onStateChange listeners to see if the new route is different than the old, and if it is, send the new page name to Quantum.

Replace <NavigationContainer> with this:

<NavigationContainer
  ref={this.navigationRef} //setup the reference so we can access the NavigationContainer later
  onReady={() => //when the NavigationContainer becomes ready, setup the initial route
    (this.routeNameRef.current = this.navigationRef.current.getCurrentRoute().name)
  }
  onStateChange={async () => { //whenever the state changes, get the new route and compare to the previous
    const previousRouteName = this.routeNameRef.current;
    const currentRouteName = this.navigationRef.current.getCurrentRoute().name;

    if (previousRouteName !== currentRouteName) { //if the names are different, we can assume the user navigated
      //call sendNewPage here (remove log when you see it's working)
      console.log('send new page: ', currentRouteName);
      QuantumMetricLibrary.sendNewPageNamed(currentRouteName)
    }

    //save the current route name for later comparison
    this.routeNameRef.current = currentRouteName;
  }}
>

That's it, you can test to make sure the send new page: console log appears, and also that in your Quantum Replay you see the new page events happening. Please contact us if you have any questions.

Full example

import 'react-native-gesture-handler';

import React, { Component } from 'react';
import {
  StyleSheet,
  View,
  Text,
  Button
} from 'react-native';


import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

import QuantumMetricLibrary from 'react-native-quantum-metric-library';

const Stack = createStackNavigator();

export default class App extends Component<{}> {

  constructor(props) {
    super(props);

    this.navigationRef = React.createRef();
    this.routeNameRef = React.createRef();
  }

  componentDidMount() {
    if (QuantumMetricLibrary && QuantumMetricLibrary.initialize) {
      QuantumMetricLibrary.initialize('mysubscription', '123');
    } else {
      console.error('error no QM lib!');
    }
  }

  render() {
    return (
      <NavigationContainer
        ref={this.navigationRef}
        onReady={() =>
          (this.routeNameRef.current = this.navigationRef.current.getCurrentRoute().name)
        }
        onStateChange={async () => {
          const previousRouteName = this.routeNameRef.current;
          const currentRouteName = this.navigationRef.current.getCurrentRoute().name;

          if (previousRouteName !== currentRouteName) {
            //call sendNewPage here
            console.log('send new page: ', currentRouteName);
            QuantumMetricLibrary.sendNewPageNamed(currentRouteName)
          }

          // Save the current route name for later comparison
          this.routeNameRef.current = currentRouteName;
        }}
      >
        <Stack.Navigator initialRouteName="Home">
          <Stack.Screen name="Home" component={HomeScreen} />
          <Stack.Screen name="Details" component={DetailsScreen} />
          <Stack.Screen name="DeeperDetails" component={DeeperDetailsScreen} />
        </Stack.Navigator>
      </NavigationContainer>
    );
  }
}

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Button title="Send New Page" onPress={() => QuantumMetricLibrary.sendNewPageNamed("ReactPageHello")}></Button>
        <Button title="Go to Details" onPress={() => this.props.navigation.push('Details')} />
      </View>
    );
  }
}


function DetailsScreen({ navigation }) {
  return(
    <View style={styles.container}>
      <Text>Details screen!</Text>
      <Button title="Push Deeper Details" onPress={() => navigation.push('DeeperDetails')} />
    </View>
  );
};

function DeeperDetailsScreen({ navigation }) {
  return(
    <View style={styles.container}>
      <Text>Deeper Details screen!</Text>
      <Button title="Push Regular Details" onPress={() => navigation.push('Details')} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

Adding a cookie and user string listener

As of version 3.0.6 of this package, you can add a cookie and user string listener via your JS/TS code, rather than having to do it through the native SDKs.

Please note that this requires version 1.0.18 of the Android SDK. On iOS, this is supported by all versions above 0.3.35.

After initializing the QM module, you can set the listener using function setSessionCookieCallbackQM(callback)

Example Doing something like the following will simply log the session cookie and user string once they are received:

componentDidMount() {
    if (QuantumMetricLibrary && QuantumMetricLibrary.initializeWithOptions) {
      QuantumMetricLibrary.initializeWithOptions('mysubscription', 'myUID', {'testModeEnabled': false, 'sslPinningEnabled': false, 'crashReportingEnabled': false});
      QuantumMetricLibrary.setSessionCookieCallbackQM((sessionCookie, userString) => {
        console.log('Got sessionCookie: ' + sessionCookie);
        console.log('Got userString: ' + userString);
      });
    } else {
      console.error('error no QM lib!');
    }
  }

The session cookie and user string can be helpful for logging and tracking purposes.

If the session cookie changes due to a new session beginning, this callback will get called again to let you know.

Manual Eventing

Quantum Metric has the ability to send manual events from your React Native application directly. This is helpful if you want a specific type of data inside Quantum Metric's platform. To send a manual event, the Quantum Metric Library has function sendEvent (eventId: number, value?: string, flags?: number):

eventId is the id of your event in the Quantum Metric platform. Please note: It is required to have an event with a corresponding id set up in the platform before sendEvent will work correctly.
value is the data you'd like to send to the Quantum Metric platform.
flags provide special instructions to the Quantum Metric platform to organize how the value is interpreted. This can be accessed by calling eventType.EventTypeHere.

Full list of Event Types:

EventTypeConversion
EventTypeLogin
EventTypeEmail
EventTypeFirstName
EventTypeLastName
EventTypeCartValue
EventTypeABN
EventTypeEncrypted

Example Let's say you'd like to record an order number, and you already have a function like this:

function completeOrder(cartValue) {
  let orderNumber = confirmPurchase(cartValue);
  if (orderNumber) {
     console.log("Purchase Confirmed!");
     return orderNumber;
  }
  return -1;
}

This will log a message when the purchase has successfully gone through. But let's go ahead and change our log to send an event to Quantum Metric. First, we'll replace our console.log with sendEvent:

function completeOrder(cartValue) {
  let orderNumber = confirmPurchase(cartValue);
  if (orderNumber) {
     QuantumMetricLibrary.sendEvent(10);
     return orderNumber;
  }
  return -1;
}

As you can see, we've provided an event id. This will now fire in the Quantum Metric platform whenever an order is confirmed. Next, let's send the order number as well:

function completeOrder(cartValue) {
  let orderNumber = confirmPurchase(cartValue);
  if (orderNumber) {
     QuantumMetricLibrary.sendEvent(10, orderNumber);
     return orderNumber;
  }
  return -1;
}

Now, the event will also include an order number when the event fires! However, this can sometimes be sensitive data, so let's encrypt that value. To do this, we'll use the flag parameter by adding the EventTypeEncrypted value:

function completeOrder(cartValue) {
  let orderNumber = confirmPurchase(cartValue);
  if (orderNumber) {
     QuantumMetricLibrary.sendEvent(10, orderNumber, QuantumMetricLibrary.eventType.EventTypeEncrypted);
     return orderNumber;
  }
  return -1;
}

And there we have it! Now, in this example, every time the app successfully completes an order, the order number will populate in the Quantum Metric platform as an encrypted value.

Another common example is order conversion:

QuantumMetricLibrary.sendEvent(123, orderValue, QuantumMetricLibrary.EventTypeConversion);

Other Features

Several other functions can be performed with the QuantumMetricLibrary, mostly related to sessions. They are as follows:

pauseQM

This will pause the current session, without ending it. Capture will cease until the session is resumed. Please note that if a session is paused for more than 30 minutes, a brand new session will begin the next time it is resumed.

QuantumMetricLibrary.pauseQM()

resumeQM

If this is called after a session has been paused, it will resume the session. If the session has been paused for more than 30 minutes, a new session will begin. If this is called while a session is still running, it will do nothing.

QuantumMetricLibrary.resumeQM()

stopQM

Calling this will end the current session. The session will be terminated and capture will cease until a new session is started.

QuantumMetricLibrary.stopQM()

resetSessionQM

Calling this will end any existing session and begin a new one. If no session is currently active, it will simply begin a new one. This function takes one boolean argument, indicating whether or not the user should be reset.

QuantumMetricLibrary.resetSessionQM(shouldResetUser)

To resume capture after it's been paused, call: QuantumMetricLibrary.resumeQM()

Release Notes

3.0.10

17 April 2023

  • Fix typescript API

3.0.9

15 February 2023

-Fix a bug related to capturing API data

3.0.8

27 June 2022

-Add support for React Native version 0.69

3.0.7

4 March 2022

-Add pause/resume API

3.0.5

3 February 2022

-Add initializeWithOptions with Android/iOS support

3.0.4

26 January 2022

-Add event type definitions, sendEvent API examples

3.0.3

29 November 2021

-Android remove support dependency

-Fix network interception race conditions

3.0.2

15 December 2021

-Add Typescript definitions

3.0.1

29 November 2021

-Documentation improvements

3.0.0

24 November 2021

-Initial launch of QuantumComponent