@influto/react-native-sdk 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/InfluTo.ts CHANGED
@@ -28,7 +28,9 @@ import type {
28
28
  AttributionResult,
29
29
  Campaign,
30
30
  TrackEventOptions,
31
- DeviceInfo
31
+ DeviceInfo,
32
+ CodeValidationResult,
33
+ SetCodeResult
32
34
  } from './types';
33
35
 
34
36
  const STORAGE_PREFIX = '@influto/';
@@ -256,6 +258,202 @@ class InfluToSDK {
256
258
  return await AsyncStorage.getItem(STORAGE_KEYS.REFERRAL_CODE);
257
259
  }
258
260
 
261
+ /**
262
+ * Get prefilled referral code (if user came via attribution link)
263
+ *
264
+ * Use this to pre-fill a promo code input field
265
+ *
266
+ * @returns Referral code if attribution exists, null otherwise
267
+ */
268
+ async getPrefilledCode(): Promise<string | null> {
269
+ const attribution = await AsyncStorage.getItem(STORAGE_KEYS.ATTRIBUTION);
270
+
271
+ if (attribution) {
272
+ const parsed = JSON.parse(attribution);
273
+ return parsed.attributed ? parsed.referralCode : null;
274
+ }
275
+
276
+ return null;
277
+ }
278
+
279
+ /**
280
+ * Validate a referral/promo code
281
+ *
282
+ * Check if a code is valid without applying it.
283
+ * Use this when user manually enters a code in your app.
284
+ *
285
+ * @param code - The referral code to validate
286
+ * @returns Validation result with campaign info if valid
287
+ *
288
+ * @example
289
+ * ```typescript
290
+ * const result = await InfluTo.validateCode('FITGURU30');
291
+ *
292
+ * if (result.valid) {
293
+ * console.log('Campaign:', result.campaign.name);
294
+ * console.log('Commission:', result.campaign.commission_percentage + '%');
295
+ * // Show custom offer based on campaign
296
+ * } else {
297
+ * console.log('Invalid code:', result.error);
298
+ * }
299
+ * ```
300
+ */
301
+ async validateCode(code: string): Promise<CodeValidationResult> {
302
+ if (!this.isInitialized) {
303
+ return {
304
+ valid: false,
305
+ error: 'SDK not initialized',
306
+ error_code: 'NETWORK_ERROR'
307
+ };
308
+ }
309
+
310
+ try {
311
+ const response = await this.apiRequest('/sdk/validate-code', {
312
+ method: 'POST',
313
+ body: JSON.stringify({ code: code.trim().toUpperCase() })
314
+ });
315
+
316
+ return response as CodeValidationResult;
317
+ } catch (error) {
318
+ if (this.config?.debug) {
319
+ console.error('[InfluTo] Code validation failed:', error);
320
+ }
321
+
322
+ return {
323
+ valid: false,
324
+ error: 'Network error or invalid response',
325
+ error_code: 'NETWORK_ERROR'
326
+ };
327
+ }
328
+ }
329
+
330
+ /**
331
+ * Manually set a referral code
332
+ *
333
+ * Use this when user enters a promo code manually (not from link click).
334
+ * This will:
335
+ * 1. Store the code locally
336
+ * 2. Set it in RevenueCat attributes automatically
337
+ * 3. Record the attribution with backend
338
+ *
339
+ * @param code - The referral code to set
340
+ * @param appUserId - Optional user ID (if available)
341
+ * @returns Result with success status
342
+ *
343
+ * @example
344
+ * ```typescript
345
+ * // User enters code manually
346
+ * const result = await InfluTo.setReferralCode('FITGURU30');
347
+ *
348
+ * if (result.success) {
349
+ * console.log('Code applied successfully');
350
+ * // Show appropriate paywall/offer
351
+ * }
352
+ * ```
353
+ */
354
+ async setReferralCode(code: string, appUserId?: string): Promise<SetCodeResult> {
355
+ if (!this.isInitialized) {
356
+ return {
357
+ success: false,
358
+ message: 'SDK not initialized'
359
+ };
360
+ }
361
+
362
+ const normalizedCode = code.trim().toUpperCase();
363
+
364
+ try {
365
+ // Store locally
366
+ await AsyncStorage.setItem(STORAGE_KEYS.REFERRAL_CODE, normalizedCode);
367
+
368
+ // Store attribution record
369
+ const attribution: AttributionResult = {
370
+ attributed: true,
371
+ referralCode: normalizedCode,
372
+ attributionMethod: 'manual_entry',
373
+ clickedAt: new Date().toISOString(),
374
+ message: 'Manually entered code'
375
+ };
376
+ await AsyncStorage.setItem(STORAGE_KEYS.ATTRIBUTION, JSON.stringify(attribution));
377
+
378
+ // Set in RevenueCat automatically
379
+ try {
380
+ const Purchases = require('react-native-purchases').default;
381
+ if (Purchases && Purchases.setAttributes) {
382
+ await Purchases.setAttributes({
383
+ referral_code: normalizedCode
384
+ });
385
+
386
+ if (this.config?.debug) {
387
+ console.log('[InfluTo] ✅ Referral code set in RevenueCat');
388
+ }
389
+ }
390
+ } catch (e) {
391
+ if (this.config?.debug) {
392
+ console.warn('[InfluTo] RevenueCat not available - set manually');
393
+ }
394
+ }
395
+
396
+ // Record with backend
397
+ const response = await this.apiRequest('/sdk/set-referral-code', {
398
+ method: 'POST',
399
+ body: JSON.stringify({
400
+ code: normalizedCode,
401
+ app_user_id: appUserId
402
+ })
403
+ });
404
+
405
+ return response as SetCodeResult;
406
+ } catch (error) {
407
+ if (this.config?.debug) {
408
+ console.error('[InfluTo] Failed to set referral code:', error);
409
+ }
410
+
411
+ return {
412
+ success: false,
413
+ message: 'Failed to set code: ' + (error as Error).message
414
+ };
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Validate and apply a referral code (combined operation)
420
+ *
421
+ * This is a convenience method that validates a code and applies it if valid.
422
+ * Use this for one-step validation + application.
423
+ *
424
+ * @param code - The referral code to validate and apply
425
+ * @param appUserId - Optional user ID
426
+ * @returns Validation result. If valid, code is automatically applied.
427
+ *
428
+ * @example
429
+ * ```typescript
430
+ * const result = await InfluTo.applyCode('FITGURU30', userId);
431
+ *
432
+ * if (result.valid) {
433
+ * // Code validated AND applied automatically
434
+ * showCustomOffer(result.campaign);
435
+ * } else {
436
+ * Alert.alert('Invalid Code', result.error);
437
+ * }
438
+ * ```
439
+ */
440
+ async applyCode(code: string, appUserId?: string): Promise<CodeValidationResult & { applied?: boolean }> {
441
+ // First validate
442
+ const validation = await this.validateCode(code);
443
+
444
+ if (!validation.valid) {
445
+ return { ...validation, applied: false };
446
+ }
447
+
448
+ // If valid, apply it
449
+ const setResult = await this.setReferralCode(code, appUserId);
450
+
451
+ return {
452
+ ...validation,
453
+ applied: setResult.success
454
+ };
455
+ }
456
+
259
457
  /**
260
458
  * Clear stored attribution data
261
459
  *