├── .npmignore ├── demos ├── appsflyer-react-native-app │ ├── .watchmanconfig │ ├── _editorconfig │ ├── app.json │ ├── .eslintrc.js │ ├── Assets │ │ ├── 1.png │ │ ├── 2.png │ │ └── 3.png │ ├── android │ │ ├── app │ │ │ ├── src │ │ │ │ ├── main │ │ │ │ │ ├── res │ │ │ │ │ │ ├── values │ │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ │ └── styles.xml │ │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ │ └── mipmap-xxxhdpi │ │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── java │ │ │ │ │ │ └── com │ │ │ │ │ │ │ └── appsflyerexample │ │ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ │ │ └── MainApplication.java │ │ │ │ │ └── AndroidManifest.xml │ │ │ │ └── debug │ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── appsflyer.billing2 │ │ │ │ │ └── ReactNativeFlipper.java │ │ │ ├── debug.keystore │ │ │ ├── proguard-rules.pro │ │ │ ├── build_defs.bzl │ │ │ └── _BUCK │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── settings.gradle │ │ ├── gradle.properties │ │ ├── build.gradle │ │ └── gradlew.bat │ ├── ios │ │ ├── AppsFlyerExample │ │ │ ├── Images.xcassets │ │ │ │ ├── Contents.json │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ ├── AppDelegate.h │ │ │ ├── main.m │ │ │ ├── AppsFlyerExample.entitlements │ │ │ ├── Info.plist │ │ │ ├── AppDelegate.m │ │ │ └── LaunchScreen.storyboard │ │ ├── assets │ │ │ └── __node_modules │ │ │ │ └── react-native │ │ │ │ └── Libraries │ │ │ │ └── LogBox │ │ │ │ └── UI │ │ │ │ └── LogBoxImages │ │ │ │ ├── close.png │ │ │ │ ├── loader.png │ │ │ │ ├── chevron-left.png │ │ │ │ ├── chevron-right.png │ │ │ │ └── alert-triangle.png │ │ ├── AppsFlyerExample.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ ├── .xcode.env │ │ ├── AppsFlyerExampleTests │ │ │ ├── Info.plist │ │ │ └── AppsFlyerExampleTests.m │ │ ├── Podfile │ │ └── AppsFlyerExample.xcodeproj │ │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── AppsFlyerExample.xcscheme │ ├── .buckconfig │ ├── .gitattributes │ ├── .prettierrc.js │ ├── index.js │ ├── __tests__ │ │ └── App-test.js │ ├── babel.config.js │ ├── metro.config.js │ ├── .gitignore │ ├── components │ │ ├── WelcomeModal.js │ │ ├── Product.js │ │ ├── AppsFlyer.js │ │ ├── Item.js │ │ └── Cart.js │ ├── README.md │ ├── package.json │ └── .flowconfig └── appsflyer-expo-app │ ├── assets │ ├── atom.png │ ├── icon.png │ ├── splash.png │ ├── favicon.png │ └── adaptive-icon.png │ ├── babel.config.js │ ├── metro.config.js │ ├── eas.json │ ├── index.js │ ├── README.md │ ├── package.json │ ├── App.js │ └── app.json ├── app.plugin.js ├── Docs ├── assets │ └── ios_files.png ├── RN_UninstallMeasurement.md ├── RN_Integration.md ├── RN_UserInvite.md ├── RN_UnifiedDeepLink.md ├── RN_Testing.md ├── RN_InAppEvents.md ├── RN_ExpoDeepLinkIntegration.md └── RN_ExpoInstallation.md ├── babel.config.js ├── tsconfig.spec.json ├── .github ├── secrets │ ├── GithubCICer.p12.gpg │ └── GithubCIApp.mobileprovision.gpg ├── bot_config.yaml ├── workflows │ ├── scripts │ │ ├── archiveApp.sh │ │ ├── updateReadme.sh │ │ ├── versionsAlignmentValidator.sh │ │ ├── releaseNotesGenerator.sh │ │ └── decryptSecrets.sh │ ├── responseToSupportIssue.yml │ ├── responseToSupportIssueOnOpen.yml │ ├── close_inactive_issues.yml │ ├── unit-tests-workflow.yml │ ├── release-QA-workflow.yml │ ├── close-inactive-issue.yml │ ├── readme_sync.yml │ ├── build-apps-workflow.yml │ ├── pre-release-workflow.yml │ ├── deploy-to-QA.yml │ └── release-Production-workflow.yml └── ISSUE_TEMPLATE │ └── config.yml ├── PurchaseConnector ├── models │ ├── missing_configuration_exception.ts │ ├── test_purchase.ts │ ├── deferred_item_replacement.ts │ ├── paused_state_context.ts │ ├── prepaid_plan.ts │ ├── validation_failure_data.ts │ ├── money_model.ts │ ├── offer_details.ts │ ├── subscription_validation_result.ts │ ├── in_app_purchase_validation_result.ts │ ├── auto_renewing_plan.ts │ ├── subscribe_with_google_info.ts │ ├── external_account_identifiers.ts │ ├── subscription_item_price_change_details.ts │ ├── ios_errors.ts │ ├── jvm_throwable.ts │ ├── subscription_purchase_line_item.ts │ ├── product_purchase.ts │ ├── subscription_purchase.ts │ └── canceled_state_context.ts ├── constants │ └── constants.ts └── utils │ └── connector_callbacks.ts ├── ios ├── RNAppsFlyer-Bridging-Header.h ├── RNAppsFlyer.xcodeproj │ ├── xcuserdata │ │ └── ppsreejith.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── RNAppsFlyer.xcscheme │ └── xcshareddata │ │ └── xcschemes │ │ └── RNAppsFlyer.xcscheme ├── AppsFlyerDeepLinkObserver.h ├── AppsFlyerDeepLinkResult.h ├── AppsFlyerAttribution.h ├── AppsFlyerConsent.h ├── PCAppsFlyer.h ├── AppsFlyerDeepLink.h ├── AppsFlyerShareInviteHelper.h ├── AppsFlyerCrossPromotionHelper.h ├── AFTransactionFetcher.swift ├── AppsFlyerLinkGenerator.h ├── AFAdRevenueData.h ├── RNAppsFlyer.h └── AppsFlyerAttribution.m ├── android ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ ├── includeConnector │ │ └── com │ │ │ └── appsflyer │ │ │ └── reactnative │ │ │ ├── MappedValidationResultListener.java │ │ │ └── PCAppsFlyerPackage.java │ │ ├── java │ │ └── com │ │ │ └── appsflyer │ │ │ └── reactnative │ │ │ ├── RNAppsFlyerPackage.java │ │ │ └── RNAppsFlyerConstants.java │ │ └── excludeConnector │ │ └── com │ │ └── appsflyer │ │ └── reactnative │ │ ├── PCAppsFlyerPackage.java │ │ └── PCAppsFlyerModule.java ├── .project └── build.gradle ├── react-native.config.js ├── expo ├── withAppsFlyer.js └── withAppsFlyerAndroid.js ├── jest.config.js ├── tsconfig.json ├── LICENSE ├── .gitignore ├── package.json ├── __tests__ └── setup.js ├── react-native-appsflyer.podspec └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | demos/ 2 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /app.plugin.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./expo/withAppsFlyer'); 2 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/_editorconfig: -------------------------------------------------------------------------------- 1 | # Windows files 2 | [*.bat] 3 | end_of_line = crlf 4 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AppsFlyerExample", 3 | "displayName": "AppsFlyerExample" 4 | } -------------------------------------------------------------------------------- /Docs/assets/ios_files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/Docs/assets/ios_files.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | // babel.config.js 2 | module.exports = { 3 | presets: ['module:metro-react-native-babel-preset'], 4 | }; -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react" 5 | } 6 | } -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /.github/secrets/GithubCICer.p12.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/.github/secrets/GithubCICer.p12.gpg -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/assets/atom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-expo-app/assets/atom.png -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-expo-app/assets/icon.png -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-expo-app/assets/splash.png -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-expo-app/assets/favicon.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/Assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/Assets/1.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/Assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/Assets/2.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/Assets/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/Assets/3.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AppsFlyerExample 3 | 4 | -------------------------------------------------------------------------------- /.github/secrets/GithubCIApp.mobileprovision.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/.github/secrets/GithubCIApp.mobileprovision.gpg -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/AppsFlyerExample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-expo-app/assets/adaptive-icon.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/.gitattributes: -------------------------------------------------------------------------------- 1 | # Windows files should use crlf line endings 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | *.bat text eol=crlf 4 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/debug.keystore -------------------------------------------------------------------------------- /PurchaseConnector/models/missing_configuration_exception.ts: -------------------------------------------------------------------------------- 1 | export class MissingConfigurationException extends Error { 2 | constructor() { 3 | super("Missing configuration for PurchaseConnector"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/metro.config.js: -------------------------------------------------------------------------------- 1 | // Learn more https://docs.expo.io/guides/customizing-metro 2 | const { getDefaultConfig } = require('expo/metro-config'); 3 | 4 | module.exports = getDefaultConfig(__dirname); 5 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | arrowParens: 'avoid', 7 | }; 8 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.github/bot_config.yaml: -------------------------------------------------------------------------------- 1 | # Configuration for AppsFlyerBot 2 | # aging issues: 3 | enableClosingAgingIssue: true 4 | enableLabelingAgingIssue: true 5 | 6 | #After how long the bot should consider an issue as obsolete (in days) 7 | agingTime: 180 8 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'AppsFlyerExample' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/AppsFlyerExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/AppsFlyerExample/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/close.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/loader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/loader.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/chevron-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/chevron-left.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/chevron-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/chevron-right.png -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/alert-triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppsFlyerSDK/appsflyer-react-native-plugin/HEAD/demos/appsflyer-react-native-app/ios/assets/__node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/alert-triangle.png -------------------------------------------------------------------------------- /PurchaseConnector/models/test_purchase.ts: -------------------------------------------------------------------------------- 1 | interface TestPurchaseJson {} 2 | 3 | export class TestPurchase { 4 | constructor() {} 5 | 6 | static fromJson(json: TestPurchaseJson): TestPurchase { 7 | return new TestPurchase(); 8 | } 9 | 10 | toJson(): TestPurchaseJson { 11 | return {}; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Sep 01 10:19:20 IDT 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ios/RNAppsFlyer-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNAppsFlyer-Bridging-Header.h 3 | // RNAppsFlyer 4 | // 5 | // Created by Amit Levy on 03/03/2025. 6 | // Copyright © 2025 Facebook. All rights reserved. 7 | // 8 | 9 | #ifndef RNAppsFlyer_Bridging_Header_h 10 | #define RNAppsFlyer_Bridging_Header_h 11 | 12 | 13 | #endif /* RNAppsFlyer_Bridging_Header_h */ 14 | -------------------------------------------------------------------------------- /.github/workflows/scripts/archiveApp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | xcodebuild -workspace AppsFlyerExample.xcworkspace \ 6 | -scheme AppsFlyerExample \ 7 | -sdk iphoneos \ 8 | -allowProvisioningUpdates \ 9 | -archivePath $PWD/build/AppsFlyerExample.xcarchive \ 10 | clean archive | xcpretty -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/AppsFlyerExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | 3 | contact_links: 4 | - name: AppsFlyer Support (Customer Assistant Chatbot) 5 | url: https://support.appsflyer.com/hc/en-us/articles/23583984402193-Using-the-Customer-Assistant-Chatbot 6 | about: For the fastest and most effective support, please contact the AppsFlyer support team using the Customer Assistant Chatbot. 7 | -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/eas.json: -------------------------------------------------------------------------------- 1 | { 2 | "cli": { 3 | "version": ">= 0.48.2" 4 | }, 5 | "build": { 6 | "development": { 7 | "developmentClient": true, 8 | "distribution": "internal" 9 | }, 10 | "preview": { 11 | "distribution": "internal" 12 | }, 13 | "production": {} 14 | }, 15 | "submit": { 16 | "production": {} 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/responseToSupportIssue.yml: -------------------------------------------------------------------------------- 1 | # This workflow triggers the org-wide reusable workflow to respond to issues labeled as 'support' 2 | on: 3 | issues: 4 | types: 5 | - labeled 6 | workflow_dispatch: 7 | 8 | jobs: 9 | add-comment: 10 | uses: AppsFlyerSDK/github-common-workflow-and-template/.github/workflows/responseToSupportIssue.yml@main 11 | secrets: inherit -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.github/workflows/responseToSupportIssueOnOpen.yml: -------------------------------------------------------------------------------- 1 | # This workflow triggers the org-wide reusable workflow to respond to newly opened issues 2 | on: 3 | issues: 4 | types: 5 | - opened 6 | workflow_dispatch: 7 | 8 | jobs: 9 | add-comment: 10 | uses: AppsFlyerSDK/github-common-workflow-and-template/.github/workflows/responseToSupportIssueOnOpen.yml@main 11 | secrets: inherit -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/index.js: -------------------------------------------------------------------------------- 1 | import 'expo-dev-client'; 2 | 3 | import { registerRootComponent } from 'expo'; 4 | 5 | import App from './App'; 6 | 7 | // registerRootComponent calls AppRegistry.registerComponent('main', () => App); 8 | // It also ensures that whether you load the app in Expo Go or in a native build, 9 | // the environment is set up appropriately 10 | registerRootComponent(App); 11 | -------------------------------------------------------------------------------- /.github/workflows/close_inactive_issues.yml: -------------------------------------------------------------------------------- 1 | # This workflow triggers the org-wide reusable workflow to close inactive issues on a schedule 2 | on: 3 | schedule: 4 | - cron: "0 10 * * *" # Runs daily at 10:00 UTC 5 | workflow_dispatch: 6 | 7 | jobs: 8 | close-issues: 9 | uses: AppsFlyerSDK/github-common-workflow-and-template/.github/workflows/close_inactive_issues.yml@main 10 | secrets: inherit -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["module:metro-react-native-babel-preset"], 3 | plugins: [ 4 | [ 5 | "module:react-native-dotenv", 6 | { 7 | moduleName: "@env", 8 | path: ".env", 9 | blacklist: null, 10 | whitelist: null, 11 | safe: false, 12 | allowUndefined: true, 13 | }, 14 | ], 15 | ], 16 | }; -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/AppsFlyerExample/AppsFlyerExample.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.associated-domains 6 | 7 | applinks:af-rn-git.onelink.me 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/src/main/includeConnector/com/appsflyer/reactnative/MappedValidationResultListener.java: -------------------------------------------------------------------------------- 1 | package com.appsflyer.reactnative; 2 | 3 | import com.appsflyer.api.PurchaseClient; 4 | import java.util.Map; 5 | 6 | public interface MappedValidationResultListener extends PurchaseClient.ValidationResultListener> { 7 | void onResponse(Map response); 8 | void onFailure(String result, Throwable error); 9 | } -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/README.md: -------------------------------------------------------------------------------- 1 | # AppsFlyer-Expo Shop Sample App 2 | 3 | Basic integration example of AppsFlyer React-Native plugin in an Expo app. Please take a look on the example `app.json` 4 | #### First run 5 | In the root folder of the the app (appsflyer-expo-app and **not** appsflyer-react-native-plugin) run:
6 | `yarn install`
7 | 8 | #### Generate native folders: 9 | run `expo prebuild` 10 | 11 | #### Android: 12 | run `npm run android` 13 | #### iOS: 14 | run `npm run ios` 15 | -------------------------------------------------------------------------------- /.github/workflows/unit-tests-workflow.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches-ignore: 7 | - 'releases/**' 8 | - 'master' 9 | workflow_call: 10 | 11 | jobs: 12 | Run-unit-tests: 13 | if: ${{ startsWith(github.head_ref, 'releases/') == false }} 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Install modules 18 | run: npm install --legacy-peer-deps 19 | - name: Run jest tests 20 | run: npm run test -------------------------------------------------------------------------------- /react-native.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | dependency: { 5 | platforms: { 6 | android: { 7 | packageImportPath: [ 8 | 'import com.appsflyer.reactnative.RNAppsFlyerPackage;', 9 | 'import com.appsflyer.reactnative.PCAppsFlyerPackage;', 10 | ].join('\n'), 11 | packageInstance: [ 12 | 'new RNAppsFlyerPackage()', 13 | 'new PCAppsFlyerPackage()', 14 | ].join(',\n'), 15 | }, 16 | }, 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /.github/workflows/release-QA-workflow.yml: -------------------------------------------------------------------------------- 1 | name: Release plugin to QA 2 | 3 | on: 4 | push: 5 | branches: 6 | - releases/[0-9].x.x/[0-9].[0-9]+.x/[0-9].[0-9]+.[0-9]+-rc[0-9]+ 7 | 8 | jobs: 9 | Run-Unit-Tests: 10 | uses: ./.github/workflows/unit-tests-workflow.yml 11 | 12 | Build-Sample-Apps: 13 | uses: ./.github/workflows/build-apps-workflow.yml 14 | secrets: inherit 15 | 16 | Deploy-To-QA: 17 | needs: [Run-Unit-Tests, Build-Sample-Apps] 18 | uses: ./.github/workflows/deploy-to-QA.yml 19 | secrets: inherit -------------------------------------------------------------------------------- /.github/workflows/scripts/updateReadme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ios_sdk_version=$(cat react-native-appsflyer.podspec | grep '\'AppsFlyerFramework\' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+') 4 | android_sdk_version=$(cat android/build.gradle | grep 'com.appsflyer:af-android-sdk' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+') 5 | sed -i -r "s/Android AppsFlyer SDK \*\*v[0-9]+\.[0-9]+\.[0-9]+\*\*/Android AppsFlyer SDK \*\*v$android_sdk_version\*\*/g" README.md 6 | sed -i -r "s/iOS AppsFlyer SDK \*\*v[0-9]+\.[0-9]+\.[0-9]+\*\*/iOS AppsFlyer SDK \*\*v$ios_sdk_version\*\*/g" README.md 7 | -------------------------------------------------------------------------------- /expo/withAppsFlyer.js: -------------------------------------------------------------------------------- 1 | const withAppsFlyerIos = require('./withAppsFlyerIos'); 2 | const withAppsFlyerAndroid = require('./withAppsFlyerAndroid'); 3 | console.log('[AppsFlyerPlugin] Main plugin loaded'); 4 | 5 | module.exports = function withAppsFlyer(config, { 6 | shouldUseStrictMode = false, 7 | shouldUsePurchaseConnector = false 8 | } = {}) { 9 | config = withAppsFlyerIos(config, { shouldUseStrictMode, shouldUsePurchaseConnector }); 10 | config = withAppsFlyerAndroid(config, { shouldUsePurchaseConnector }); 11 | return config; 12 | }; 13 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /PurchaseConnector/models/deferred_item_replacement.ts: -------------------------------------------------------------------------------- 1 | export type DeferredItemReplacementJson = { 2 | productId: string; 3 | }; 4 | 5 | export class DeferredItemReplacement { 6 | productId: string; 7 | 8 | constructor(productId: string) { 9 | this.productId = productId; 10 | } 11 | 12 | static fromJson(json: DeferredItemReplacementJson): DeferredItemReplacement { 13 | return new DeferredItemReplacement(json.productId); 14 | } 15 | 16 | toJson(): DeferredItemReplacementJson { 17 | return { 18 | productId: this.productId, 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /PurchaseConnector/models/paused_state_context.ts: -------------------------------------------------------------------------------- 1 | type PausedStateContextJson = { 2 | autoResumeTime: string; 3 | }; 4 | 5 | export class PausedStateContext { 6 | autoResumeTime: string; 7 | 8 | constructor(autoResumeTime: string) { 9 | this.autoResumeTime = autoResumeTime; 10 | } 11 | 12 | static fromJson(json: PausedStateContextJson): PausedStateContext { 13 | return new PausedStateContext(json.autoResumeTime); 14 | } 15 | 16 | toJson(): PausedStateContextJson { 17 | return { 18 | autoResumeTime: this.autoResumeTime, 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /PurchaseConnector/models/prepaid_plan.ts: -------------------------------------------------------------------------------- 1 | export type PrepaidPlanJson = { 2 | allowExtendAfterTime?: string; 3 | }; 4 | 5 | export class PrepaidPlan { 6 | allowExtendAfterTime?: string; 7 | 8 | constructor(allowExtendAfterTime?: string) { 9 | this.allowExtendAfterTime = allowExtendAfterTime; 10 | } 11 | 12 | static fromJson(json: PrepaidPlanJson): PrepaidPlan { 13 | return new PrepaidPlan(json.allowExtendAfterTime); 14 | } 15 | 16 | toJson(): PrepaidPlanJson { 17 | return { 18 | allowExtendAfterTime: this.allowExtendAfterTime, 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.github/workflows/close-inactive-issue.yml: -------------------------------------------------------------------------------- 1 | # This workflow close issue and add comment after the issue labaled as 'inactive' 2 | 3 | name: Close issue 4 | on: 5 | issues: 6 | types: 7 | - labeled 8 | jobs: 9 | close-inactive-issue: 10 | if: github.event.label.name == 'Inactive' 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Close issue due to inactivity 14 | uses: peter-evans/close-issue@v2 15 | with: 16 | issue-number: ${{ github.event.issue.number }} 17 | comment: | 18 | This issue is closed due to inactivity. If the issue continue, please open a new one. 19 | -------------------------------------------------------------------------------- /ios/RNAppsFlyer.xcodeproj/xcuserdata/ppsreejith.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RNAppsFlyer.xcscheme 8 | 9 | orderHint 10 | 11 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 58B511DA1A9E6C8500147676 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PurchaseConnector/models/validation_failure_data.ts: -------------------------------------------------------------------------------- 1 | export type ValidationFailureDataJson = { 2 | status: number; 3 | description: string; 4 | }; 5 | 6 | export default class ValidationFailureData { 7 | status: number; 8 | description: string; 9 | 10 | constructor(status: number, description: string) { 11 | this.status = status; 12 | this.description = description; 13 | } 14 | 15 | static fromJson(json: ValidationFailureDataJson): ValidationFailureData { 16 | return new ValidationFailureData(json.status, json.description); 17 | } 18 | 19 | toJson(): ValidationFailureDataJson { 20 | return { 21 | status: this.status, 22 | description: this.description, 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /PurchaseConnector/models/money_model.ts: -------------------------------------------------------------------------------- 1 | export type MoneyArgs = { 2 | currencyCode: string; 3 | nanos: number; 4 | units: number; 5 | }; 6 | 7 | export class Money { 8 | currencyCode: string; 9 | nanos: number; 10 | units: number; 11 | 12 | constructor(currencyCode: string, nanos: number, units: number) { 13 | this.currencyCode = currencyCode; 14 | this.nanos = nanos; 15 | this.units = units; 16 | } 17 | 18 | static fromJson(json: MoneyArgs): Money { 19 | return new Money(json.currencyCode, json.nanos, json.units); 20 | } 21 | 22 | toJson(): MoneyArgs { 23 | return { 24 | currencyCode: this.currencyCode, 25 | nanos: this.nanos, 26 | units: this.units, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /demos/appsflyer-expo-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "expoappsflyer", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "expo start --dev-client", 6 | "android": "expo run:android", 7 | "ios": "expo run:ios", 8 | "web": "expo start --web", 9 | "eject": "expo eject" 10 | }, 11 | "dependencies": { 12 | "expo": "~45.0.0", 13 | "expo-dev-client": "~0.9.5", 14 | "expo-splash-screen": "~0.15.1", 15 | "expo-status-bar": "~1.3.0", 16 | "react": "17.0.2", 17 | "react-dom": "17.0.2", 18 | "react-native": "0.68.2", 19 | "react-native-appsflyer": "6.6.0", 20 | "react-native-web": "0.17.7" 21 | }, 22 | "devDependencies": { 23 | "@babel/core": "^7.12.9" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /ios/AppsFlyerDeepLinkObserver.h: -------------------------------------------------------------------------------- 1 | // 2 | // AFSDKDeepLinkObserver.h 3 | // AppsFlyerLib 4 | // 5 | // Created by Andrii Hahan on 09.09.2020. 6 | // 7 | 8 | #import 9 | 10 | @class AppsFlyerDeepLinkResult; 11 | 12 | NS_SWIFT_NAME(DeepLinkObserverDelegate) 13 | @protocol AppsFlyerDeepLinkObserverDelegate 14 | 15 | @optional 16 | - (void)didResolveDeepLink:(AppsFlyerDeepLinkResult *_Nonnull)result; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | NS_SWIFT_NAME(DeepLinkObserver) 22 | @interface AppsFlyerDeepLinkObserver : NSObject 23 | 24 | @property(weak, nonatomic) id delegate; 25 | @property NSTimeInterval timeoutInterval; 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const { createJsWithBabelPreset } = require('ts-jest'); 2 | 3 | const jsWithBabelPreset = createJsWithBabelPreset({ 4 | tsconfig: 'tsconfig.json', // Ensure this matches your tsconfig file 5 | babelConfig: true, 6 | }); 7 | 8 | module.exports = { 9 | preset: 'react-native', 10 | transform: { 11 | ...jsWithBabelPreset.transform, 12 | '^.+\\.js$': '/node_modules/react-native/jest/preprocessor.js', 13 | }, 14 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 15 | modulePathIgnorePatterns: ['/demos/'], 16 | testMatch: [ 17 | '/__tests__/**/*.test.ts?(x)', 18 | '/__tests__/index.test.js?(x)', 19 | ], 20 | setupFiles: ['/__tests__/setup.js'], 21 | }; -------------------------------------------------------------------------------- /.github/workflows/readme_sync.yml: -------------------------------------------------------------------------------- 1 | name: Sync `docs` directory to ReadMe 2 | 3 | # Run workflow for every push to the `main` branch 4 | on: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | sync: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout this repo 14 | uses: actions/checkout@v3 15 | 16 | # Run GitHub Action to sync docs in `documentation` directory 17 | - name: GitHub Action 18 | # We recommend specifying a fixed version, i.e. @7.5.0 19 | # Docs: https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#example-using-versioned-actions 20 | uses: readmeio/rdme@7.5.0 21 | with: 22 | rdme: docs ./Docs --key=${{ secrets.README_SYNC_API_KEY }} --version=0.1 -------------------------------------------------------------------------------- /PurchaseConnector/constants/constants.ts: -------------------------------------------------------------------------------- 1 | class AppsFlyerConstants { 2 | // Adding method constants 3 | static readonly SUBSCRIPTION_VALIDATION_SUCCESS: string = 'subscriptionValidationSuccess'; 4 | static readonly SUBSCRIPTION_VALIDATION_FAILURE: string = 'subscriptionValidationFailure'; 5 | static readonly IN_APP_PURCHASE_VALIDATION_SUCCESS: string = 'inAppPurchaseValidationSuccess'; 6 | static readonly IN_APP_PURCHASE_VALIDATION_FAILURE: string = 'inAppPurchaseValidationFailure'; 7 | static readonly DID_RECEIVE_PURCHASE_REVENUE_VALIDATION_INFO: string = 8 | "onDidReceivePurchaseRevenueValidationInfo"; 9 | 10 | // Adding key constants 11 | static readonly RESULT: string = "result"; 12 | static readonly ERROR: string = "error"; 13 | } 14 | 15 | export default AppsFlyerConstants; -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/android/app/src/main/java/com/appsflyerexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.appsflyerexample; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | 8 | public class MainActivity extends ReactActivity { 9 | 10 | @Override 11 | public void onNewIntent(Intent intent) { 12 | super.onNewIntent(intent); 13 | setIntent(intent); 14 | } 15 | 16 | /** 17 | * Returns the name of the main component registered from JavaScript. This is used to schedule 18 | * rendering of the component. 19 | */ 20 | @Override 21 | protected String getMainComponentName() { 22 | return "AppsFlyerExample"; 23 | } 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(null); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | const path = require('path'); 9 | 10 | const localPackagePaths = [ 11 | path.resolve(__dirname, '../../'), // Path to `react-native-appsflyer` 12 | ]; 13 | 14 | module.exports = { 15 | transformer: { 16 | getTransformOptions: async () => ({ 17 | transform: { 18 | experimentalImportSupport: false, 19 | inlineRequires: true, 20 | }, 21 | }), 22 | }, 23 | resolver: { 24 | nodeModulesPaths: [path.resolve(__dirname, 'node_modules'), ...localPackagePaths], 25 | extraNodeModules: { 26 | 'react-native-appsflyer': path.resolve(__dirname, '../../'), 27 | }, 28 | }, 29 | watchFolders: [...localPackagePaths], 30 | }; -------------------------------------------------------------------------------- /ios/AppsFlyerDeepLinkResult.h: -------------------------------------------------------------------------------- 1 | // 2 | // AFSDKDeeplinkResult.h 3 | // AppsFlyerLib 4 | // 5 | // Created by Andrii Hahan on 20.08.2020. 6 | // 7 | 8 | #import 9 | 10 | @class AppsFlyerDeepLink; 11 | 12 | typedef NS_CLOSED_ENUM(NSUInteger, AFSDKDeepLinkResultStatus) { 13 | AFSDKDeepLinkResultStatusNotFound, 14 | AFSDKDeepLinkResultStatusFound, 15 | AFSDKDeepLinkResultStatusFailure, 16 | } NS_SWIFT_NAME(DeepLinkResultStatus); 17 | 18 | NS_SWIFT_NAME(DeepLinkResult) 19 | @interface AppsFlyerDeepLinkResult : NSObject 20 | 21 | - (nonnull instancetype)init NS_UNAVAILABLE; 22 | + (nonnull instancetype)new NS_UNAVAILABLE; 23 | 24 | @property(readonly) AFSDKDeepLinkResultStatus status; 25 | 26 | @property(readonly, nullable) AppsFlyerDeepLink *deepLink; 27 | @property(readonly, nullable) NSError *error; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ios/AppsFlyerAttribution.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppsFlyerAttribution.h 3 | // Pods 4 | // 5 | // Created by Amit Kremer on 11/02/2021. 6 | // 7 | #ifndef AppsFlyerAttribution_h 8 | #define AppsFlyerAttribution_h 9 | #endif /* AppsFlyerAttribution_h */ 10 | 11 | @interface AppsFlyerAttribution : NSObject 12 | @property BOOL RNAFBridgeReady; 13 | 14 | + (instancetype _Nonnull )shared; 15 | - (void) continueUserActivity:(NSUserActivity *_Nonnull)userActivity restorationHandler:(void (^_Nullable)(NSArray *_Nullable))restorationHandler; 16 | - (void) handleOpenUrl:(NSURL *_Nonnull)url options:(NSDictionary *_Nullable)options; 17 | - (void) handleOpenUrl:(NSURL *_Nonnull)url sourceApplication:(NSString *_Nullable)sourceApplication annotation:(id _Nullable)annotation; 18 | 19 | @end 20 | 21 | static NSString * _Nonnull const RNAFBridgeInitializedNotification = @"bridgeInitialized"; 22 | -------------------------------------------------------------------------------- /android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | react-native-appsflyer 4 | Project android_ created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | 19 | 1671214559722 20 | 21 | 30 22 | 23 | org.eclipse.core.resources.regexFilterMatcher 24 | node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /PurchaseConnector/models/offer_details.ts: -------------------------------------------------------------------------------- 1 | export type OfferDetailsJson = { 2 | offerTags?: string[]; 3 | basePlanId: string; 4 | offerId?: string; 5 | }; 6 | 7 | export class OfferDetails { 8 | offerTags?: string[]; 9 | basePlanId: string; 10 | offerId?: string; 11 | 12 | constructor( 13 | offerTags: string[] | undefined, 14 | basePlanId: string, 15 | offerId: string | undefined 16 | ) { 17 | this.offerTags = offerTags; 18 | this.basePlanId = basePlanId; 19 | this.offerId = offerId; 20 | } 21 | 22 | static fromJson(json: OfferDetailsJson): OfferDetails { 23 | return new OfferDetails(json.offerTags, json.basePlanId, json.offerId); 24 | } 25 | 26 | toJson(): OfferDetailsJson { 27 | return { 28 | offerTags: this.offerTags, 29 | basePlanId: this.basePlanId, 30 | offerId: this.offerId, 31 | }; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/AppsFlyerExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ios/AppsFlyerConsent.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppsFlyerConsent.h 3 | // AppsFlyerLib 4 | // 5 | // Created by Veronica Belyakov on 14/01/2024. 6 | // 7 | #import 8 | 9 | NS_ASSUME_NONNULL_BEGIN 10 | 11 | @interface AppsFlyerConsent : NSObject 12 | 13 | @property (nonatomic, readonly, assign) BOOL isUserSubjectToGDPR; 14 | @property (nonatomic, readonly, assign) BOOL hasConsentForDataUsage; 15 | @property (nonatomic, readonly, assign) BOOL hasConsentForAdsPersonalization; 16 | 17 | - (instancetype)init NS_UNAVAILABLE; 18 | + (instancetype)new NS_UNAVAILABLE; 19 | 20 | - (instancetype)initForGDPRUserWithHasConsentForDataUsage:(BOOL)hasConsentForDataUsage 21 | hasConsentForAdsPersonalization:(BOOL)hasConsentForAdsPersonalization NS_DESIGNATED_INITIALIZER; 22 | - (instancetype)initNonGDPRUser NS_DESIGNATED_INITIALIZER; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", // Specifies the ECMAScript target version 4 | "module": "commonjs", // Specifies the module code generation method 5 | "jsx": "react-native", // Supports JSX in React Native 6 | "strict": true, // Enables strict type-checking options 7 | "esModuleInterop": true, // Enables compatibility between CommonJS and ES Modules 8 | "skipLibCheck": true, // Skips type checking of declaration files 9 | "forceConsistentCasingInFileNames": true, // Ensures consistent casing in file names 10 | "noEmit": true // Prevents the compiler from emitting output files 11 | }, 12 | "include": ["src/**/*", "__tests__/**/*"], // Includes application source code and tests 13 | "exclude": ["node_modules", "babel.config.js", "metro.config.js", "jest.config.js"] // Excludes unnecessary files 14 | } -------------------------------------------------------------------------------- /PurchaseConnector/utils/connector_callbacks.ts: -------------------------------------------------------------------------------- 1 | import { IosError, JVMThrowable } from "../models"; 2 | 3 | // Type definition for a general-purpose listener. 4 | export type PurchaseConnectorListener = (data: any) => void; 5 | 6 | // Type definition for a listener which gets called when the `PurchaseConnectorImpl` receives purchase revenue validation info for iOS. 7 | export type OnReceivePurchaseRevenueValidationInfo = (validationInfo?: Map, error?: IosError) => void; 8 | 9 | // Invoked when a 200 OK response is received from the server. 10 | // Note: An INVALID purchase is considered to be a successful response and will also be returned by this callback. 11 | export type OnResponse = (result?: Map) => void; 12 | 13 | // Invoked when a network exception occurs or a non 200/OK response is received from the server. 14 | export type OnFailure = (result: string, error?: JVMThrowable) => void; -------------------------------------------------------------------------------- /.github/workflows/scripts/versionsAlignmentValidator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Plugin version from release branch 4 | PLUGIN_VERSION=$1 5 | 6 | # Gets the plugin version for platform_extension_v2 in every platform 7 | IOS_PLUGIN_VERSION=$(cat ios/RNAppsFlyer.h | grep 'kAppsFlyerPluginVersion' | grep -Eo '[0-9].[0-9]+.[0-9]') 8 | ANDROID_PLUGIN_VERSION=$(cat android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java | grep 'PLUGIN_VERSION' | grep -Eo '[0-9].[0-9]+.[0-9]') 9 | 10 | # Check if PLUGIN_VERSION, IOS_PLUGIN_VERSION and ANDROID_PLUGIN_VERSION are equal 11 | echo "version from branch: $PLUGIN_VERSION\nplatform_extension_v2 ios: $IOS_PLUGIN_VERSION\nplatform_extension_v2 android: $ANDROID_PLUGIN_VERSION" 12 | if [[ "$PLUGIN_VERSION" == "$IOS_PLUGIN_VERSION" && "$PLUGIN_VERSION" == "$ANDROID_PLUGIN_VERSION" ]]; then 13 | echo "platform_extension_v2 version is aligned" 14 | else 15 | echo "platform_extension_v2 version is different!" 16 | exit 1 17 | fi -------------------------------------------------------------------------------- /.github/workflows/scripts/releaseNotesGenerator.sh: -------------------------------------------------------------------------------- 1 | JIRA_TOKEN=$1 2 | JIRA_FIXED_VERSION=$2 3 | 4 | fixed_version_found=false 5 | curl -X GET https://appsflyer.atlassian.net/rest/api/3/project/11723/versions --user $JIRA_TOKEN | jq -r '.[] | .name+""+.id' | while read version ; do 6 | if [[ "$version" == *"$JIRA_FIXED_VERSION"* ]] ;then 7 | echo "$JIRA_FIXED_VERSION Found!" 8 | fixed_version_found=true 9 | version_id=${version#"$JIRA_FIXED_VERSION"} 10 | echo $(curl -X GET https://appsflyer.atlassian.net/rest/api/3/search?jql=fixVersion=$version_id --user $JIRA_TOKEN | jq -r '.issues[] | "- " + .fields["summary"]+"@"') > "$JIRA_FIXED_VERSION-releasenotes".txt 11 | sed -i -r -e "s/@ /\n/gi" "$JIRA_FIXED_VERSION-releasenotes".txt 12 | sed -i -r -e "s/@/\n/gi" "$JIRA_FIXED_VERSION-releasenotes".txt 13 | cat "$JIRA_FIXED_VERSION-releasenotes".txt 14 | fi 15 | done 16 | if [ fixed_version_found == false ];then 17 | echo "$JIRA_FIXED_VERSION is not found!" 18 | exit 1 19 | fi -------------------------------------------------------------------------------- /ios/PCAppsFlyer.h: -------------------------------------------------------------------------------- 1 | #if __has_include() // ver >= 0.40 2 | #import 3 | #import 4 | #else // ver < 0.40 5 | #import "RCTBridgeModule.h" 6 | #import "RCTEventEmitter.h" 7 | #endif 8 | 9 | #import 10 | #if __has_include() 11 | #import 12 | 13 | @interface PCAppsFlyer: RCTEventEmitter 14 | // This is the PCAppsFlyer if the AppsFlyerPurchaseConnector is set to true in the podfile 15 | @property (nonatomic, strong) NSDictionary *purchaseRevenueParams; 16 | @property (nonatomic, strong) NSDictionary *purchaseRevenueStoreKit2Params; 17 | @end 18 | 19 | #else 20 | 21 | @interface PCAppsFlyer: RCTEventEmitter 22 | // This is the PCAppsFlyer if the AppsFlyerPurchaseConnector is set to false in the podfile 23 | @end 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /PurchaseConnector/models/subscription_validation_result.ts: -------------------------------------------------------------------------------- 1 | import { SubscriptionPurchase } from "./subscription_purchase"; 2 | import { ValidationFailureDataJson } from "./validation_failure_data"; 3 | 4 | export default class SubscriptionValidationResult { 5 | success: boolean; 6 | subscriptionPurchase?: SubscriptionPurchase; 7 | failureData?: ValidationFailureDataJson; 8 | 9 | constructor( 10 | success: boolean, 11 | subscriptionPurchase?: SubscriptionPurchase, 12 | failureData?: ValidationFailureDataJson 13 | ) { 14 | this.success = success; 15 | this.subscriptionPurchase = subscriptionPurchase; 16 | this.failureData = failureData; 17 | } 18 | 19 | static fromJson(json: any): SubscriptionValidationResult { 20 | return new SubscriptionValidationResult( 21 | json.success, 22 | json.subscriptionPurchase, 23 | json.failureData 24 | ); 25 | } 26 | 27 | toJson(): any { 28 | return { 29 | success: this.success, 30 | subscriptionPurchase: this.subscriptionPurchase, 31 | failureData: this.failureData, 32 | }; 33 | } 34 | } -------------------------------------------------------------------------------- /PurchaseConnector/models/in_app_purchase_validation_result.ts: -------------------------------------------------------------------------------- 1 | import { ProductPurchase } from "./product_purchase"; 2 | import { ValidationFailureDataJson } from "./validation_failure_data"; 3 | 4 | export default class InAppPurchaseValidationResult { 5 | success: boolean; 6 | productPurchase?: ProductPurchase; 7 | failureData?: ValidationFailureDataJson; 8 | 9 | constructor( 10 | success: boolean, 11 | productPurchase?: ProductPurchase, 12 | failureData?: ValidationFailureDataJson 13 | ) { 14 | this.success = success; 15 | this.productPurchase = productPurchase; 16 | this.failureData = failureData; 17 | } 18 | 19 | static fromJson(json: any): InAppPurchaseValidationResult { 20 | return new InAppPurchaseValidationResult( 21 | json.success, 22 | json.productPurchase, 23 | json.failureData 24 | ); 25 | } 26 | 27 | toJson(): any { 28 | return { 29 | success: this.success, 30 | productPurchase: this.productPurchase, 31 | failureData: this.failureData, 32 | }; 33 | } 34 | } -------------------------------------------------------------------------------- /android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerPackage.java: -------------------------------------------------------------------------------- 1 | package com.appsflyer.reactnative; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.JavaScriptModule; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.Arrays; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class RNAppsFlyerPackage implements ReactPackage { 14 | 15 | public RNAppsFlyerPackage() { 16 | } 17 | 18 | 19 | public List> createJSModules() { 20 | return Collections.emptyList(); 21 | } 22 | 23 | @Override 24 | public List createNativeModules(ReactApplicationContext reactContext) { 25 | return Arrays.asList(new RNAppsFlyerModule(reactContext)); 26 | } 27 | 28 | @Override 29 | public List createViewManagers(ReactApplicationContext reactContext) { 30 | return Collections.emptyList(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /android/src/main/excludeConnector/com/appsflyer/reactnative/PCAppsFlyerPackage.java: -------------------------------------------------------------------------------- 1 | package com.appsflyer.reactnative; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.JavaScriptModule; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.Arrays; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class PCAppsFlyerPackage implements ReactPackage { 14 | 15 | public PCAppsFlyerPackage() { 16 | } 17 | 18 | 19 | public List> createJSModules() { 20 | return Collections.emptyList(); 21 | } 22 | 23 | @Override 24 | public List createNativeModules(ReactApplicationContext reactContext) { 25 | return Arrays.asList(new PCAppsFlyerModule(reactContext)); 26 | } 27 | 28 | @Override 29 | public List createViewManagers(ReactApplicationContext reactContext) { 30 | return Collections.emptyList(); 31 | } 32 | } -------------------------------------------------------------------------------- /android/src/main/includeConnector/com/appsflyer/reactnative/PCAppsFlyerPackage.java: -------------------------------------------------------------------------------- 1 | package com.appsflyer.reactnative; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.JavaScriptModule; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.Arrays; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class PCAppsFlyerPackage implements ReactPackage { 14 | 15 | public PCAppsFlyerPackage() { 16 | } 17 | 18 | 19 | public List> createJSModules() { 20 | return Collections.emptyList(); 21 | } 22 | 23 | @Override 24 | public List createNativeModules(ReactApplicationContext reactContext) { 25 | return Arrays.asList(new PCAppsFlyerModule(reactContext)); 26 | } 27 | 28 | @Override 29 | public List createViewManagers(ReactApplicationContext reactContext) { 30 | return Collections.emptyList(); 31 | } 32 | } -------------------------------------------------------------------------------- /.github/workflows/scripts/decryptSecrets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eo pipefail 3 | 4 | gpg --quiet --batch --yes --decrypt --passphrase="$IOS_KEYS" --output ./.github/secrets/GithubCIApp.mobileprovision.mobileprovision ./.github/secrets/GithubCIApp.mobileprovision.gpg 5 | gpg --quiet --batch --yes --decrypt --passphrase="$IOS_KEYS" --output ./.github/secrets/GithubCICer.p12 ./.github/secrets/GithubCICer.p12.gpg 6 | 7 | mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles 8 | 9 | cp ./.github/secrets/GithubCIApp.mobileprovision.mobileprovision ~/Library/MobileDevice/Provisioning\ Profiles/GithubCIApp.mobileprovision.mobileprovision 10 | 11 | 12 | security create-keychain -p "$IOS_KEYS" build.keychain 13 | security import ./.github/secrets/GithubCICer.p12 -t agg -k ~/Library/Keychains/build.keychain -P "$IOS_KEYS" -A 14 | 15 | security list-keychains -s ~/Library/Keychains/build.keychain 16 | security default-keychain -s ~/Library/Keychains/build.keychain 17 | security unlock-keychain -p "$IOS_KEYS" ~/Library/Keychains/build.keychain 18 | 19 | security set-key-partition-list -S apple-tool:,apple: -s -k "$IOS_KEYS" ~/Library/Keychains/build.keychain -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | *.keystore 42 | !debug.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | 61 | #Secrets 62 | .env 63 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/components/WelcomeModal.js: -------------------------------------------------------------------------------- 1 | /* @flow weak */ 2 | 3 | import React from 'react'; 4 | import { 5 | View, 6 | StyleSheet, 7 | } from 'react-native'; 8 | import { Button, Overlay, Text, Image } from 'react-native-elements'; 9 | 10 | const WelcomeModal = ({isFirstLaunch, dismissOverlay}) => ( 11 | 12 | Welcome To Our Shop! 13 | This is you first time here, Enjoy! 14 | 15 | 16 | 17 | 18 | ); 19 | 20 | export default WelcomeModal; 21 | 22 | const styles = StyleSheet.create({ 23 | container: { 24 | flex: 1, 25 | }, 26 | text: { 27 | alignSelf: 'center', 28 | marginTop: 20 29 | }, 30 | image: { 31 | width: 100, 32 | height: 100, 33 | marginTop: 20 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /android/src/main/excludeConnector/com/appsflyer/reactnative/PCAppsFlyerModule.java: -------------------------------------------------------------------------------- 1 | package com.appsflyer.reactnative; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.util.Log; 6 | 7 | import com.facebook.react.bridge.ReactApplicationContext; 8 | import com.facebook.react.bridge.ReactContext; 9 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 10 | import com.facebook.react.bridge.ReactMethod; 11 | 12 | public class PCAppsFlyerModule extends ReactContextBaseJavaModule { 13 | 14 | public PCAppsFlyerModule(ReactApplicationContext reactContext) { 15 | super(reactContext); 16 | Log.d("AppsFlyer", "PurchaseConnector inclusion status: " + BuildConfig.INCLUDE_CONNECTOR); 17 | } 18 | 19 | @Override 20 | public String getName() { 21 | return "PCAppsFlyer"; 22 | } 23 | 24 | @ReactMethod 25 | public void addListener(String eventName) { 26 | // Keep: Required for RN built in Event Emitter Calls. 27 | } 28 | 29 | @ReactMethod 30 | public void removeListeners(Integer count) { 31 | // Keep: Required for RN built in Event Emitter Calls. 32 | } 33 | } -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/ios/AppsFlyerExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/README.md: -------------------------------------------------------------------------------- 1 | # AppsFlyer Shop Sample App 2 | 3 | 4 | 5 | 6 | Example of how to use AppsFlyer React-Native plugin. In this app we demonstrate how to use basic initialization, in-app events (logEvent), and deep linking with UDL and GCD parameters.
7 | Also in this app we use:
8 | [React-Navigation v6](https://reactnavigation.org/docs/getting-started)
9 | [React-Native-Elements](https://reactnativeelements.com/) 10 | 11 | #### First runt 12 | In the root folder of the the app (AppsFlyerExample and **not** appsflyer-react-native-plugin) run:
13 | `npm install`
14 | and then: `cd ios && pod install` 15 | #### Android: 16 | run `npm run android` 17 | #### iOS: 18 | run `npm run ios` 19 | -------------------------------------------------------------------------------- /PurchaseConnector/models/auto_renewing_plan.ts: -------------------------------------------------------------------------------- 1 | import { SubscriptionItemPriceChangeDetailsJson, SubscriptionItemPriceChangeDetails } from "./subscription_item_price_change_details"; 2 | 3 | export type AutoRenewingPlanJson = { 4 | autoRenewEnabled?: boolean; 5 | priceChangeDetails?: SubscriptionItemPriceChangeDetailsJson; 6 | }; 7 | 8 | export class AutoRenewingPlan { 9 | autoRenewEnabled?: boolean; 10 | priceChangeDetails?: SubscriptionItemPriceChangeDetails; 11 | 12 | constructor( 13 | autoRenewEnabled?: boolean, 14 | priceChangeDetails?: SubscriptionItemPriceChangeDetails 15 | ) { 16 | this.autoRenewEnabled = autoRenewEnabled; 17 | this.priceChangeDetails = priceChangeDetails; 18 | } 19 | 20 | static fromJson(json: AutoRenewingPlanJson): AutoRenewingPlan { 21 | return new AutoRenewingPlan( 22 | json.autoRenewEnabled, 23 | json.priceChangeDetails && 24 | SubscriptionItemPriceChangeDetails.fromJson(json.priceChangeDetails) 25 | ); 26 | } 27 | 28 | toJson(): AutoRenewingPlanJson { 29 | return { 30 | autoRenewEnabled: this.autoRenewEnabled, 31 | priceChangeDetails: this.priceChangeDetails?.toJson(), 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ios/AppsFlyerDeepLink.h: -------------------------------------------------------------------------------- 1 | // 2 | // AFSDKDeeplink.h 3 | // AppsFlyerLib 4 | // 5 | // Created by Andrii Hahan on 20.08.2020. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | NS_SWIFT_NAME(DeepLink) 13 | @interface AppsFlyerDeepLink : NSObject 14 | 15 | - (nonnull instancetype)init NS_UNAVAILABLE; 16 | + (nonnull instancetype)new NS_UNAVAILABLE; 17 | 18 | @property (readonly, nonnull) NSDictionary *clickEvent; 19 | @property (readonly, nullable) NSString *deeplinkValue; 20 | @property (readonly, nullable) NSString *matchType; 21 | @property (readonly, nullable) NSString *clickHTTPReferrer; 22 | @property (readonly, nullable) NSString *mediaSource; 23 | @property (readonly, nullable) NSString *campaign; 24 | @property (readonly, nullable) NSString *campaignId; 25 | @property (readonly, nullable) NSString *afSub1; 26 | @property (readonly, nullable) NSString *afSub2; 27 | @property (readonly, nullable) NSString *afSub3; 28 | @property (readonly, nullable) NSString *afSub4; 29 | @property (readonly, nullable) NSString *afSub5; 30 | @property (readonly) BOOL isDeferred; 31 | 32 | - (NSString *)toString; 33 | 34 | @end 35 | 36 | NS_ASSUME_NONNULL_END 37 | -------------------------------------------------------------------------------- /PurchaseConnector/models/subscribe_with_google_info.ts: -------------------------------------------------------------------------------- 1 | export type SubscribeWithGoogleInfoJson = { 2 | emailAddress: string; 3 | familyName: string; 4 | givenName: string; 5 | profileId: string; 6 | profileName: string; 7 | }; 8 | 9 | export class SubscribeWithGoogleInfo { 10 | emailAddress: string; 11 | familyName: string; 12 | givenName: string; 13 | profileId: string; 14 | profileName: string; 15 | 16 | constructor( 17 | emailAddress: string, 18 | familyName: string, 19 | givenName: string, 20 | profileId: string, 21 | profileName: string 22 | ) { 23 | this.emailAddress = emailAddress; 24 | this.familyName = familyName; 25 | this.givenName = givenName; 26 | this.profileId = profileId; 27 | this.profileName = profileName; 28 | } 29 | 30 | static fromJson(json: SubscribeWithGoogleInfoJson): SubscribeWithGoogleInfo { 31 | return new SubscribeWithGoogleInfo( 32 | json.emailAddress, 33 | json.familyName, 34 | json.givenName, 35 | json.profileId, 36 | json.profileName 37 | ); 38 | } 39 | 40 | //This is primitve types so we can use ...this (spread operator) 41 | toJson(): SubscribeWithGoogleInfoJson { 42 | return { ...this }; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /demos/appsflyer-react-native-app/components/Product.js: -------------------------------------------------------------------------------- 1 | /* @flow weak */ 2 | 3 | import React from 'react'; 4 | import {View, Text, StyleSheet} from 'react-native'; 5 | import {Card, Button, Icon} from 'react-native-elements' 6 | 7 | const Product = ({product, goToProductScreen, addToCart}) => ( 8 | goToProductScreen(product, addToCart)}/> 11 | {product.name} 12 | {`${product.price} USD`} 13 |