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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pnlight/sdk-react-native

v0.7.3

Published

React Native wrapper for PNLight iOS binary SDK

Readme

PNLight SDK - React Native Package

npm package

A React Native wrapper for the PNLight iOS SDK.

Installation

Install the package in your React Native or Expo app:

npm install @pnlight/sdk-react-native

or:

yarn add @pnlight/sdk-react-native

Then install iOS pods:

cd ios
pod install

Requirements

  • iOS 13.0+
  • React Native app with CocoaPods
  • Swift 5.7+

This package is iOS-only. Android is not supported.


iOS Setup

DivKit Pod Source

If you use RemoteUiView, add the DivKit CocoaPods source to your app's ios/Podfile before the default CocoaPods source:

source 'https://github.com/divkit/divkit-ios.git'
source 'https://cdn.cocoapods.org/'

Then run:

cd ios
pod install

Required Frameworks

Make sure the host iOS app links the frameworks required by PNLight:

  • StoreKit.framework
  • CoreMotion.framework
  • AdSupport.framework
  • AppTrackingTransparency.framework

For apps that need IDFA tracking, add NSUserTrackingUsageDescription to Info.plist:

<key>NSUserTrackingUsageDescription</key>
<string>This app uses device tracking to provide analytics and improve user experience.</string>

Usage

Initialization

Initialize PNLight before using analytics, attribution, or Remote UI:

import { initialize } from "@pnlight/sdk-react-native";

await initialize("your-api-key");

Event Logging

import { logEvent } from "@pnlight/sdk-react-native";

await logEvent("purchase_completed", {
  product_id: "premium_subscription",
  amount: 9.99,
  currency: "USD",
});

Attribution

Send attribution data from external providers before requesting UI config.

import { addAttribution } from "@pnlight/sdk-react-native";

const success = await addAttribution(
  "appsFlyer",
  { af_status: "Non-organic" },
  "your-appsflyer-id",
);

AppsFlyer Integration Example

PNLight does not depend on the AppsFlyer initialization order — it only needs the conversion data, delivered via addAttribution. Make sure the conversion ("attribution success") callback is not processed before PNLight is initialized: if it can fire earlier, store the conversion data in memory and call addAttribution once initialize completes.

AppsFlyer requires the ATT prompt to complete before it starts. If PNLight is initialized before ATT authorization, call updateIdfa() after the prompt completes so PNLight receives the granted IDFA.

import appsFlyer from "react-native-appsflyer";
import { requestTrackingPermission } from "react-native-tracking-transparency";
import {
  addAttribution,
  initialize,
  updateIdfa,
} from "@pnlight/sdk-react-native";

const getAppsFlyerUID = () =>
  new Promise<string | null>((resolve) => {
    appsFlyer.getAppsFlyerUID((error, uid) => {
      if (error) {
        console.error("AppsFlyer UID error", error);
        resolve(null);
        return;
      }

      resolve(uid);
    });
  });

export async function startSdks() {
  await initialize("your-api-key");

  // Request ATT, then pass the granted IDFA to PNLight.
  await requestTrackingPermission();
  await updateIdfa();

  // Start AppsFlyer after ATT completes (an AppsFlyer requirement).
  appsFlyer.onInstallConversionData(async (conversionData) => {
    const appsFlyerId = await getAppsFlyerUID();

    await addAttribution(
      "appsFlyer",
      conversionData?.data ?? conversionData,
      appsFlyerId,
    );
  });

  appsFlyer.initSdk(
    {
      devKey: "your-appsflyer-dev-key",
      appId: "your-ios-app-id",
      isDebug: false,
      onInstallConversionDataListener: true,
    },
    (result) => {
      console.log("AppsFlyer initialized", result);
    },
    (error) => {
      console.error("AppsFlyer init error", error);
    },
  );
}

Supported providers:

  • appsFlyer
  • firebase
  • facebook

User Identity

import { getUserId } from "@pnlight/sdk-react-native";

const userId = await getUserId();

RemoteUiView - Server-driven UI

RemoteUiView fetches and renders a server-driven layout from PNLight for a given placement. It calls getUIConfig(placement) internally, renders the native view, and emits action events to JavaScript.

When using external attribution providers such as AppsFlyer, send attribution as early as possible (see the AppsFlyer example above). getUIConfig waits for attribution data internally when attributionRequired is true (the default), so no manual delay is needed.

import React from "react";
import { StyleSheet, View } from "react-native";
import { RemoteUiView, type ActionEvent } from "@pnlight/sdk-react-native";

export function PaywallScreen() {
  const handleAction = (event: ActionEvent) => {
    if (event.logId === "purchase_button") {
      const productId = event.params.id;
      // Start purchase flow for productId
    } else if (event.logId === "close_button") {
      // Close the screen
    }
  };

  return (
    <View style={styles.root}>
      <RemoteUiView
        placement="paywall"
        onAction={handleAction}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  root: {
    flex: 1,
  },
});

Manual Config Fetching

Use getUIConfig if you need to fetch the placement configuration yourself. When attributionRequired is true (the default), the SDK waits for attribution data internally before returning:

import { getUIConfig } from "@pnlight/sdk-react-native";

const config = await getUIConfig("paywall");
const configWithoutAttributionWait = await getUIConfig("paywall", false);

API Reference

SDK Methods

| Method | Description | | ---------------------------------------------- | ------------------------------------------------------------- | | initialize(apiKey, baseDomain?) | Initialize the SDK with your API key and optional base domain | | logEvent(eventName, eventArgs?) | Log a custom event with optional arguments | | addAttribution(provider, data?, identifier?) | Send attribution data from AppsFlyer, Firebase, or Facebook | | getUserId() | Get or create a stable user identifier | | updateIdfa() | Send the current IDFA to PNLight after the ATT prompt completes | | prefetchUIConfig(placement) | Prefetch a UI config into the in-memory cache | | getUIConfig(placement, attributionRequired?) | Fetch a UI config; waits for attribution by default |

RemoteUiView

| Prop | Type | Description | | --------------------- | ------------------------------ | ----------------------------------------------------------------------- | | placement | string | PNLight placement identifier | | style | StyleProp<ViewStyle> | Optional React Native style | | secure | boolean | Deprecated. Secure rendering is controlled by the backend response. | | preventRecording | boolean | Deprecated. Capture blocking is controlled by the backend. | | attributionRequired | boolean | Wait for attribution before returning config; defaults to true | | onAction | (event: ActionEvent) => void | Called when a custom action is triggered |

ActionEvent

| Property | Type | Description | | -------- | ------------------------ | ------------------------------------------------- | | url | string | Full URL string of the triggered action | | scheme | string | URL scheme | | path | string | URL path component | | params | Record<string, string> | Query parameters extracted from the URL | | logId | string \| undefined | Log ID for the triggered action | | action | string \| undefined | Raw action value when provided by the native view |

UIConfig

| Property | Type | Description | | ------------ | ------------------------------ | ---------------------------------------- | | config | string \| null | Remote UI JSON config | | parameters | Record<string, any> \| null | Placement parameters returned by PNLight | | debug | boolean \| null \| undefined | Debug flag returned by PNLight |


Support

For support and questions, visit docs.pnlight.app.