@viss-develop/affiliate-sdk
Version:
React Native Affiliate SDK with AppsFlyer integration
421 lines (420 loc) • 16.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initAppsFlyer = exports.createCustomConversion = exports.createBuyConversion = exports.clearStoredAffiliateData = exports.getStoredInstallData = exports.getStoredCampaignId = exports.getStoredClickId = exports.getFromLocalStorage = void 0;
// Dynamic imports to avoid React Native conflicts
let appsFlyer = null;
let AsyncStorage = null;
// Import conversion service and types
const conversionService_1 = __importDefault(require("./services/conversionService"));
// Secure logging utility
class SecureLogger {
constructor() {
this.isDebug = false;
}
setDebugMode(enabled) {
this.isDebug = enabled;
}
maskSensitiveData(data) {
if (!data)
return data;
const masked = Object.assign({}, data);
// Mask sensitive keys
const sensitiveKeys = ['devKey', 'apiToken', 'clickId', 'click_id', 'campaignId', 'campaign_id'];
sensitiveKeys.forEach(key => {
if (masked[key]) {
masked[key] = typeof masked[key] === 'string'
? `${masked[key].substring(0, 4)}***${masked[key].substring(masked[key].length - 4)}`
: '***';
}
});
// Mask full response data
if (masked.fullResponseData) {
masked.fullResponseData = '[MASKED]';
}
// Mask data object
if (masked.data && typeof masked.data === 'object') {
masked.data = '[MASKED_DATA]';
}
return masked;
}
log(message, data) {
if (data) {
if (this.isDebug) {
console.log(message, data);
}
else {
console.log(message, this.maskSensitiveData(data));
}
}
else {
console.log(message);
}
}
error(message, error) {
if (error) {
if (this.isDebug) {
console.error(message, error);
}
else {
console.error(message, this.maskSensitiveData(error));
}
}
else {
console.error(message);
}
}
warn(message, data) {
if (data) {
if (this.isDebug) {
console.warn(message, data);
}
else {
console.warn(message, this.maskSensitiveData(data));
}
}
else {
console.warn(message);
}
}
}
const logger = new SecureLogger();
// Initialize modules dynamically
const initializeModules = async () => {
if (!appsFlyer) {
appsFlyer = require('react-native-appsflyer').default;
}
if (!AsyncStorage) {
AsyncStorage = require('@react-native-async-storage/async-storage').default;
}
};
let conversionService = null;
// Local storage keys
const STORAGE_KEYS = {
CLICK_ID: 'affiliate_click_id',
CAMPAIGN_ID: 'affiliate_campaign_id',
INSTALL_DATA: 'affiliate_install_data'
};
// Helper function to save data to local storage
const saveToLocalStorage = async (key, value) => {
try {
await AsyncStorage.setItem(key, String(value));
logger.log(`💾 Saved ${key} to local storage:`, value);
}
catch (error) {
logger.error(`❌ Failed to save ${key} to local storage:`, error);
}
};
// Helper function to get data from local storage
const getFromLocalStorage = async (key) => {
try {
const value = await AsyncStorage.getItem(key);
logger.log(`📖 Retrieved ${key} from local storage:`, value);
return value;
}
catch (error) {
logger.error(`❌ Failed to get ${key} from local storage:`, error);
return null;
}
};
exports.getFromLocalStorage = getFromLocalStorage;
// Helper functions to get stored affiliate data
const getStoredClickId = async () => {
return await (0, exports.getFromLocalStorage)(STORAGE_KEYS.CLICK_ID);
};
exports.getStoredClickId = getStoredClickId;
const getStoredCampaignId = async () => {
const value = await (0, exports.getFromLocalStorage)(STORAGE_KEYS.CAMPAIGN_ID);
return value ? Number(value) : null;
};
exports.getStoredCampaignId = getStoredCampaignId;
const getStoredInstallData = async () => {
try {
const data = await (0, exports.getFromLocalStorage)(STORAGE_KEYS.INSTALL_DATA);
return data ? JSON.parse(data) : null;
}
catch (error) {
logger.error('❌ Failed to parse stored install data:', error);
return null;
}
};
exports.getStoredInstallData = getStoredInstallData;
// Helper function to clear stored affiliate data
const clearStoredAffiliateData = async () => {
try {
await AsyncStorage.multiRemove([
STORAGE_KEYS.CLICK_ID,
STORAGE_KEYS.CAMPAIGN_ID,
STORAGE_KEYS.INSTALL_DATA
]);
logger.log('🗑️ Cleared stored affiliate data');
}
catch (error) {
logger.error('❌ Failed to clear stored affiliate data:', error);
}
};
exports.clearStoredAffiliateData = clearStoredAffiliateData;
// Updated Buy Conversion function that uses stored data with optional parameters
const createBuyConversion = async (orderId, actionTime, totalDiscount, totalSaleAmount, totalCommission, clientIp, userAgent, conversionParts) => {
try {
// Initialize modules first
await initializeModules();
// Check if conversion service is initialized
if (!conversionService) {
const errorMsg = 'Conversion service not initialized. Please call initAppsFlyer first.';
console.error('❌ Buy Conversion failed:', errorMsg);
return {
success: false,
error: errorMsg,
data: null
};
}
// Get clickId and campaignId from local storage
const clickId = await (0, exports.getStoredClickId)();
const campaignId = await (0, exports.getStoredCampaignId)();
if (!clickId || !campaignId) {
const errorMsg = 'No stored clickId or campaignId found. Please ensure AppsFlyer has been initialized and install data received.';
console.error('❌ Buy Conversion failed:', errorMsg);
return {
success: false,
error: errorMsg,
data: null
};
}
logger.log('🛒 Creating Buy Conversion with stored data:', { clickId, campaignId, orderId, actionTime, totalDiscount, totalSaleAmount, totalCommission, clientIp, userAgent, conversionParts });
// Create conversion request with stored data and optional parameters
const conversionRequest = {
clickId,
campaignId: campaignId,
action: 'buy',
orderId,
actionTime,
totalDiscount,
totalSaleAmount,
totalCommission,
clientIp,
userAgent,
conversionParts
};
const result = await conversionService.createConversion(conversionRequest);
logger.log('✅ Buy Conversion created successfully:', result);
return {
success: true,
error: null,
data: result
};
}
catch (error) {
const errorMsg = error instanceof Error ? error.message : 'Unknown error occurred';
logger.error('❌ Buy Conversion failed:', errorMsg);
return {
success: false,
error: errorMsg,
data: null
};
}
};
exports.createBuyConversion = createBuyConversion;
// Updated Custom Conversion function that gets clickId and campaignId from SDK if not provided
const createCustomConversion = async (clickId, campaignId, action, orderId, actionTime, totalDiscount, totalSaleAmount, totalCommission, clientIp, userAgent, conversionParts) => {
try {
// Initialize modules first
await initializeModules();
// Check if conversion service is initialized
if (!conversionService) {
const errorMsg = 'Conversion service not initialized. Please call initAppsFlyer first.';
logger.error('❌ Custom Conversion failed:', errorMsg);
return {
success: false,
error: errorMsg,
data: null
};
}
// Validate required parameters
if (!clickId || !campaignId) {
const errorMsg = 'clickId and campaignId are required. Either provide them as parameters or ensure AppsFlyer has been initialized and install data received.';
logger.error('❌ Custom Conversion failed:', errorMsg);
return {
success: false,
error: errorMsg,
data: null
};
}
logger.log('🎯 Creating Custom Conversion:', {
clickId: clickId,
campaignId: campaignId,
action,
orderId,
actionTime,
totalDiscount,
totalSaleAmount,
totalCommission,
clientIp,
userAgent,
conversionParts,
source: clickId ? 'parameter' : 'sdk'
});
// Create conversion request with provided data and optional parameters
const conversionRequest = {
clickId: clickId,
campaignId: campaignId,
action,
orderId,
actionTime,
totalDiscount,
totalSaleAmount,
totalCommission,
clientIp,
userAgent,
conversionParts
};
const result = await conversionService.createConversion(conversionRequest);
logger.log('✅ Custom Conversion created successfully:', result);
return {
success: true,
error: null,
data: result
};
}
catch (error) {
const errorMsg = error instanceof Error ? error.message : 'Unknown error occurred';
logger.error('❌ Custom Conversion failed:', errorMsg);
return {
success: false,
error: errorMsg,
data: null
};
}
};
exports.createCustomConversion = createCustomConversion;
const initAppsFlyer = async (config) => {
try {
// Initialize modules first
await initializeModules();
// Initialize conversion service with API token
conversionService = new conversionService_1.default(undefined, config.apiToken);
// Set debug mode for logger
logger.setDebugMode(config.isDebug || false);
logger.log('🚀 Initializing AppsFlyer with config:', {
devKey: config.devKey,
appId: config.appId,
isDebug: config.isDebug
});
appsFlyer.initSdk({
devKey: config.devKey,
isDebug: config.isDebug || true,
appId: config.appId,
onInstallConversionDataListener: true,
onDeepLinkListener: true,
}, (result) => {
logger.log('✅ AppsFlyer initialized successfully:', result);
}, (error) => {
logger.error('❌ AppsFlyer init failed:', error);
});
// Set up install conversion data listener
appsFlyer.onInstallConversionData((res) => {
const msg = `onInstallConversionData: ${JSON.stringify(res)}`;
logger.log(msg);
if (res != null && typeof res === 'object') {
const status = res.status;
const data = res.data;
logger.log('📊 Install Conversion Data Details:', {
status,
data,
fullResponseData: res,
keys: Object.keys(res)
});
// Handle the correct structure where data is directly in res.data
if (data && typeof data === 'object') {
const afStatus = data.af_status;
const isFirstLaunch = data.is_first_launch;
const clickId = data.click_id; // Note: it's click_id, not clickId
const campaignId = data.campaign_id ? Number(data.campaign_id) : null; // Convert to number
logger.log('🔍 Parsed Data:', {
status,
afStatus,
isFirstLaunch,
clickId,
campaignId,
data
});
// Call the callback if provided
if (config.onInstallConversionData) {
config.onInstallConversionData(Object.assign({ status, data: data }, res));
}
let isOrganic = afStatus === 'Organic';
// Handle first launch
if (isFirstLaunch && !isOrganic) {
// Save clickId and campaignId to local storage if available
logger.log('🚀 First launch detected!');
// Auto-create conversion if clickId and campaignId are available
if (clickId && campaignId && conversionService) {
logger.log('🔄 Auto-creating conversion for install...');
conversionService.createConversion({
clickId,
campaignId,
action: 'install'
}).then((result) => {
if (result.success) {
logger.log('💾 Saving clickId and campaignId to local storage...');
saveToLocalStorage(STORAGE_KEYS.CLICK_ID, clickId);
saveToLocalStorage(STORAGE_KEYS.CAMPAIGN_ID, campaignId);
// Also save the full install data for reference
saveToLocalStorage(STORAGE_KEYS.INSTALL_DATA, JSON.stringify(data));
logger.log('✅ Auto-conversion created successfully:', result);
}
else {
logger.error('❌ Auto-conversion failed:', result.error);
}
}).catch((error) => {
logger.error('❌ Auto-conversion error:', error);
});
}
else {
logger.warn('⚠️ Missing required data for auto-conversion:');
logger.log('🔍 Available fields:', {
click_id: clickId,
campaign_id: campaignId,
af_status: afStatus,
is_first_launch: isFirstLaunch
});
if (!clickId)
logger.warn('❌ click_id is missing');
if (!campaignId)
logger.warn('❌ campaign_id is missing or null');
}
}
else if (isOrganic) {
logger.log('🌱 Organic install detected, skipping auto-conversion');
}
else if (!isFirstLaunch) {
logger.log('🔄 Not first launch, skipping auto-conversion');
logger.log('📊 Install details:', {
click_id: clickId,
campaign_id: campaignId,
af_status: afStatus,
is_first_launch: isFirstLaunch,
media_source: data.media_source,
campaign: data.campaign
});
}
}
else {
logger.warn('⚠️ Could not find conversion data in res.data');
logger.log('🔍 Available keys in response:', Object.keys(res));
logger.log('🔍 Full response structure:', JSON.stringify(res, null, 2));
}
}
else {
logger.warn('⚠️ Received invalid install conversion data:', res);
}
});
}
catch (error) {
logger.error('❌ AppsFlyer initialization failed:', error);
throw error;
}
};
exports.initAppsFlyer = initAppsFlyer;