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

@viss-develop/affiliate-sdk

v1.0.4

Published

React Native Affiliate SDK with AppsFlyer integration

Readme

React Native Affiliate SDK

A React Native SDK for tracking affiliate conversions with AppsFlyer integration and enterprise-grade security.

Features

  • AppsFlyer Integration: Automatic install conversion tracking
  • Buy Conversion: Create buy conversions using stored clickId and campaignId
  • Custom Conversion: Create custom conversions with explicit clickId and campaignId
  • Local Storage: Automatic storage and retrieval of affiliate data
  • TypeScript Support: Full type definitions included
  • Optional Parameters: Support for detailed conversion data (orderId, amounts, conversion parts, etc.)
  • Enterprise Security: Production-safe logging with automatic data masking
  • Debug Mode Control: Separate logging behavior for development and production

Installation

npm install @viss-develop/affiliate-sdk

Quick Start

1. Initialize AppsFlyer

import { initAppsFlyer } from '@viss-develop/affiliate-sdk';

// Development (with secure logging)
await initAppsFlyer({
  devKey: 'your-dev-key',
  appId: 'your-app-id',
  apiToken: 'your-api-token',
  isDebug: true, // Shows masked logs for debugging
  onInstallConversionData: (data) => {
    console.log('📱 Install Conversion Data received:', data);
    
    if (data.status === 'success') {
      console.log('✅ Install conversion data success');
      
      const conversionData = data.data;
      if (conversionData) {
        if (conversionData.is_first_launch) {
          console.log('🎉 First launch detected!');
        }
        
        // Check if auto-conversion was triggered
        if (conversionData.click_id && conversionData.campaign_id) {
          console.log('🔄 Auto-conversion triggered for install');
        }
      }
    }
  }
});

// Production (no sensitive data logged)
await initAppsFlyer({
  devKey: 'your-dev-key',
  appId: 'your-app-id',
  apiToken: 'your-api-token',
  isDebug: false, // No logs, maximum security
  onInstallConversionData: (data) => {
    // Handle conversion data
  }
});

2. Create Buy Conversion

import { createBuyConversion } from '@viss-develop/affiliate-sdk';

// Simple buy conversion using stored data
const handleSimpleBuyConversion = async () => {
  try {
    const result = await createBuyConversion();
    
    if (result.success) {
      console.log('✅ Buy conversion created:', result.data);
    } else {
      console.error('❌ Buy conversion failed:', result.error);
    }
  } catch (error) {
    console.error('❌ Unexpected error:', error);
  }
};

// Buy conversion with optional data
const handleBuyConversionWithData = async () => {
  try {
    const result = await createBuyConversion(
      'ord.001', // orderId
      Date.now(), // actionTime
      { amount: 10000, currency: 'VND' }, // totalDiscount
      { amount: 100000, currency: 'VND' }, // totalSaleAmount
      { amount: 5000, currency: 'VND' }, // totalCommission
      '192.168.1.1', // clientIp
      'React Native App', // userAgent
      [ // conversionParts
        {
          sku: 'product_001',
          url: 'https://example.com/product/001',
          price: 100000,
          discount: 10000,
          saleAmount: 90000,
          currency: 'VND',
          name: 'Sample Product',
          categoryName: 'Electronics',
          categoryId: 'cat_001',
          quantity: 1,
          commission: {
            amount: 5000,
            currency: 'VND'
          },
          calculateBy: 'FIXED'
        }
      ]
    );
    
    if (result.success) {
      console.log('✅ Buy conversion with data created:', result.data);
    } else {
      console.error('❌ Buy conversion with data failed:', result.error);
    }
  } catch (error) {
    console.error('❌ Unexpected error:', error);
  }
};

3. Create Custom Conversion

import { createCustomConversion, getStoredClickId, getStoredCampaignId } from '@viss-develop/affiliate-sdk';

// Custom conversion using stored data
const handleCustomConversionFromStored = async () => {
  try {
    // Get stored clickId and campaignId first
    const storedClickId = await getStoredClickId();
    const storedCampaignId = await getStoredCampaignId();
    
    if (!storedClickId || !storedCampaignId) {
      console.error('❌ No stored clickId or campaignId found');
      return;
    }
    
    // Use stored data for custom conversion
    const result = await createCustomConversion(
      storedClickId, // use stored clickId
      storedCampaignId, // use stored campaignId
      'buy', // action
      'stored_ord.001', // orderId
      Date.now(), // actionTime
      undefined, // totalDiscount
      { amount: 75000, currency: 'VND' }, // totalSaleAmount
      { amount: 3750, currency: 'VND' }, // totalCommission
      undefined, // clientIp
      undefined, // userAgent
      [ // conversionParts
        {
          sku: 'registration_success',
          url: 'https://example.com/register',
          price: 0,
          discount: 0,
          saleAmount: 0,
          currency: 'VND',
          name: 'User Registration',
          categoryName: 'Registration',
          categoryId: 'reg_001',
          quantity: 1,
          commission: {
            amount: 10000,
            currency: 'VND'
          },
          calculateBy: 'FIXED'
        }
      ]
    );
    
    if (result.success) {
      console.log('✅ Custom conversion with stored data created:', result.data);
    } else {
      console.error('❌ Custom conversion with stored data failed:', result.error);
    }
  } catch (error) {
    console.error('❌ Unexpected error:', error);
  }
};

// Custom conversion with explicit values
const handleCustomConversionExplicit = async () => {
  try {
    const result = await createCustomConversion(
      'GKbQfVgyCIFkTvVmZHyMPOTpKLHGkE', // clickId (required)
      9, // campaignId (required)
      'register', // action
      'custom_ord.001', // orderId
      Date.now(), // actionTime
      undefined, // totalDiscount
      { amount: 0, currency: 'VND' }, // totalSaleAmount
      { amount: 10000, currency: 'VND' }, // totalCommission
      undefined, // clientIp
      undefined, // userAgent
      undefined // conversionParts
    );
    
    if (result.success) {
      console.log('✅ Custom conversion with explicit values created:', result.data);
    } else {
      console.error('❌ Custom conversion with explicit values failed:', result.error);
    }
  } catch (error) {
    console.error('❌ Unexpected error:', error);
  }
};

4. Get Stored Data

import { getStoredClickId, getStoredCampaignId, getStoredInstallData } from '@viss-develop/affiliate-sdk';

const handleGetStoredData = async () => {
  try {
    const clickId = await getStoredClickId();
    const campaignId = await getStoredCampaignId();
    const installData = await getStoredInstallData();
    
    console.log('📊 Stored Data:', {
      clickId: clickId || 'Not found',
      campaignId: campaignId || 'Not found',
      installData: installData || 'Not found'
    });
  } catch (error) {
    console.error('❌ Failed to get stored data:', error);
  }
};

Security Features

The SDK includes enterprise-grade security with automatic data masking and production-safe logging.

Data Masking

Sensitive information is automatically masked in logs:

// Before: "abc123def456"
// After:  "abc1***def4"

// Masked keys:
- devKey → "abc1***def4"
- apiToken → "tok1***ken4" 
- clickId → "cli1***id4"
- campaignId → "***"

Debug Mode Control

// Development (debug on) - Shows masked logs
await initAppsFlyer({
  devKey: 'your-dev-key',
  appId: 'your-app-id',
  apiToken: 'your-api-token',
  isDebug: true  // ✅ Shows masked logs for debugging
});

// Production (debug off) - No sensitive data logged
await initAppsFlyer({
  devKey: 'your-dev-key',
  appId: 'your-app-id',
  apiToken: 'your-api-token',
  isDebug: false // ✅ No logs, maximum security
});

API Reference

initAppsFlyer(config)

Initialize AppsFlyer SDK and store affiliate data.

Parameters:

  • config (AppsFlyerConfig): Configuration object
    • devKey (string): AppsFlyer dev key
    • appId (string): App ID (iOS) or package name (Android)
    • apiToken (string): API token for conversion service
    • isDebug (boolean): Enable/disable debug logging (default: false)
    • onInstallConversionData (function): Callback for install conversion data

createBuyConversion(orderId?, actionTime?, totalDiscount?, totalSaleAmount?, totalCommission?, clientIp?, userAgent?, conversionParts?)

Create buy conversion using stored clickId and campaignId.

Parameters:

  • orderId (string, optional): Order ID
  • actionTime (number, optional): Action timestamp
  • totalDiscount (MonetaryAmount, optional): Total discount
  • totalSaleAmount (MonetaryAmount, optional): Total sale amount
  • totalCommission (MonetaryAmount, optional): Total commission
  • clientIp (string, optional): Client IP address
  • userAgent (string, optional): User agent string
  • conversionParts (ConversionPart[], optional): Conversion parts array

Returns: Promise with result object

{
  success: boolean,
  data?: any,
  error?: string
}

createCustomConversion(clickId, campaignId, action?, orderId?, actionTime?, totalDiscount?, totalSaleAmount?, totalCommission?, clientIp?, userAgent?, conversionParts?)

Create custom conversion with explicit clickId and campaignId.

Parameters:

  • clickId (string, required): Click ID from affiliate link
  • campaignId (number, required): Campaign ID
  • action (string, optional): Action type (default: 'buy')
  • orderId (string, optional): Order ID
  • actionTime (number, optional): Action timestamp
  • totalDiscount (MonetaryAmount, optional): Total discount
  • totalSaleAmount (MonetaryAmount, optional): Total sale amount
  • totalCommission (MonetaryAmount, optional): Total commission
  • clientIp (string, optional): Client IP address
  • userAgent (string, optional): User agent string
  • conversionParts (ConversionPart[], optional): Conversion parts array

Returns: Promise with result object (same as createBuyConversion)

getStoredClickId()

Get stored clickId from local storage.

Returns: Promise<string | null>

getStoredCampaignId()

Get stored campaignId from local storage.

Returns: Promise<number | null>

getStoredInstallData()

Get stored install data from local storage.

Returns: Promise<InstallConversionData | null>

clearStoredAffiliateData()

Clear all stored affiliate data.

Returns: Promise

Types

MonetaryAmount

interface MonetaryAmount {
  amount: number;
  currency: string;
}

ConversionPart

interface ConversionPart {
  sku?: string;
  url?: string;
  price?: number;
  discount?: number;
  saleAmount?: number;
  currency?: string;
  name?: string;
  categoryName?: string;
  categoryId?: string;
  quantity?: number;
  commission?: MonetaryAmount;
  calculateBy?: string;
}

InstallConversionData

interface InstallConversionData {
  af_status: string;
  is_first_launch: boolean;
  click_id?: string;
  campaign_id?: number;
  media_source?: string;
  campaign?: string;
  // ... other AppsFlyer data
}

How it works

  1. Initialization: AppsFlyer is initialized with dev key and app ID
  2. Data Storage: When install conversion data is received, clickId and campaignId are stored locally
  3. Buy Conversion: Uses stored data to create buy conversions
  4. Custom Conversion: Uses explicit clickId and campaignId or retrieves from storage
  5. Security: All sensitive data is automatically masked in logs
  6. Optional Data: All functions support optional parameters like orderId, amounts, conversion parts, etc.

Example App

A complete demo app is included in the example/ directory with the following features:

  • Create Buy Conversion (Simple): Create buy conversion with stored data
  • Create Buy Conversion (With Data): Create buy conversion with optional parameters
  • Create Custom Conversion (From Stored): Create custom conversion using stored data
  • Get Stored Data: View stored data in the SDK

Run Example App

cd example
npm install
npx react-native run-ios
# or
npx react-native run-android

Security

The SDK includes production-safe logging with automatic data masking. Sensitive information like devKey, apiToken, clickId, and campaignId are automatically masked in logs.

Production Usage

// For production - no sensitive data logged
await initAppsFlyer({
  devKey: 'your-dev-key',
  appId: 'your-app-id',
  apiToken: 'your-api-token',
  isDebug: false // ✅ No sensitive data exposure
});

Development Usage

// For development - sensitive data masked
await initAppsFlyer({
  devKey: 'your-dev-key',
  appId: 'your-app-id',
  apiToken: 'your-api-token',
  isDebug: true // ✅ Shows masked logs: "abc1***def4"
});

For detailed security information, see SECURITY.md.

Example Usage

See example-usage-with-optional-data.js for complete usage examples with all optional parameters.

Version History

  • v1.0.3: Added enterprise security with automatic data masking
  • v1.0.2: Flattened API parameters, improved TypeScript types
  • v1.0.1: Initial release with basic functionality

License

MIT License