Skip to content

Commit 542689c

Browse files
authored
Add AppsFlyer plugin (#27)
* initial commit * add deeplink and core api for appsflyer func and update iosDelegation method * resolve review comments and clean up code * add Cody's fixes and suggestions * fix snake case prefixes for rev and currency * add comment to deep link code
1 parent 75afa3a commit 542689c

File tree

9 files changed

+475
-27
lines changed

9 files changed

+475
-27
lines changed

Examples/apps/DestinationsExample/DestinationsExample.xcodeproj/project.pbxproj

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
965DC1232669947F00DDF9C7 /* FirebaseDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965DC1222669947F00DDF9C7 /* FirebaseDestination.swift */; };
2727
965DC1262671656C00DDF9C7 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 965DC1252671656C00DDF9C7 /* GoogleService-Info.plist */; };
2828
9697C1F52679156C00B87EC1 /* Segment_Logo_Avatar_Grey-1024.png in Resources */ = {isa = PBXBuildFile; fileRef = 9697C1F42679156C00B87EC1 /* Segment_Logo_Avatar_Grey-1024.png */; };
29+
BA384C9826824F3700AFEA1B /* AppsFlyerLib in Frameworks */ = {isa = PBXBuildFile; productRef = BA384C9726824F3700AFEA1B /* AppsFlyerLib */; };
30+
BA384C9A2682973300AFEA1B /* AppsFlyerDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA384C992682973300AFEA1B /* AppsFlyerDestination.swift */; };
2931
/* End PBXBuildFile section */
3032

3133
/* Begin PBXFileReference section */
@@ -46,13 +48,16 @@
4648
965DC1222669947F00DDF9C7 /* FirebaseDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseDestination.swift; sourceTree = "<group>"; };
4749
965DC1252671656C00DDF9C7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
4850
9697C1F42679156C00B87EC1 /* Segment_Logo_Avatar_Grey-1024.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Segment_Logo_Avatar_Grey-1024.png"; sourceTree = "<group>"; };
51+
BA384C992682973300AFEA1B /* AppsFlyerDestination.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppsFlyerDestination.swift; sourceTree = "<group>"; };
52+
BA384C9D2686609000AFEA1B /* DestinationsExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DestinationsExample.entitlements; sourceTree = "<group>"; };
4953
/* End PBXFileReference section */
5054

5155
/* Begin PBXFrameworksBuildPhase section */
5256
469F7B01266011690038E773 /* Frameworks */ = {
5357
isa = PBXFrameworksBuildPhase;
5458
buildActionMask = 2147483647;
5559
files = (
60+
BA384C9826824F3700AFEA1B /* AppsFlyerLib in Frameworks */,
5661
469EC8E0266828860068F9E3 /* FlurryAnalyticsSPM in Frameworks */,
5762
469EC8D0266066130068F9E3 /* SystemConfiguration.framework in Frameworks */,
5863
965DC1212669942800DDF9C7 /* FirebaseAnalytics in Frameworks */,
@@ -85,6 +90,7 @@
8590
469F7B06266011690038E773 /* DestinationsExample */ = {
8691
isa = PBXGroup;
8792
children = (
93+
BA384C9D2686609000AFEA1B /* DestinationsExample.entitlements */,
8894
469F7B1E266012CB0038E773 /* destination_plugins */,
8995
469F7B07266011690038E773 /* AppDelegate.swift */,
9096
469F7B09266011690038E773 /* SceneDelegate.swift */,
@@ -110,6 +116,7 @@
110116
469F7B1E266012CB0038E773 /* destination_plugins */ = {
111117
isa = PBXGroup;
112118
children = (
119+
BA384C992682973300AFEA1B /* AppsFlyerDestination.swift */,
113120
469F7B24266013320038E773 /* AdjustDestination.swift */,
114121
965DC0F92668077400DDF9C7 /* AmplitudeSession.swift */,
115122
965DC1222669947F00DDF9C7 /* FirebaseDestination.swift */,
@@ -151,6 +158,7 @@
151158
965DC0FD2668079400DDF9C7 /* Mixpanel */,
152159
469EC8DF266828860068F9E3 /* FlurryAnalyticsSPM */,
153160
965DC1202669942800DDF9C7 /* FirebaseAnalytics */,
161+
BA384C9726824F3700AFEA1B /* AppsFlyerLib */,
154162
);
155163
productName = DestinationsExample;
156164
productReference = 469F7B04266011690038E773 /* DestinationsExample.app */;
@@ -184,6 +192,7 @@
184192
965DC0FC2668079400DDF9C7 /* XCRemoteSwiftPackageReference "mixpanel-swift" */,
185193
469EC8DE266828860068F9E3 /* XCRemoteSwiftPackageReference "FlurrySwiftPackage" */,
186194
965DC11F2669942800DDF9C7 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
195+
BA384C9626824F3700AFEA1B /* XCRemoteSwiftPackageReference "AppsFlyerFramework" */,
187196
);
188197
productRefGroup = 469F7B05266011690038E773 /* Products */;
189198
projectDirPath = "";
@@ -214,6 +223,7 @@
214223
isa = PBXSourcesBuildPhase;
215224
buildActionMask = 2147483647;
216225
files = (
226+
BA384C9A2682973300AFEA1B /* AppsFlyerDestination.swift in Sources */,
217227
469F7B20266012CB0038E773 /* FlurryDestination.swift in Sources */,
218228
469F7B0C266011690038E773 /* ViewController.swift in Sources */,
219229
965DC0FA2668077400DDF9C7 /* MixpanelDestination.swift in Sources */,
@@ -370,14 +380,18 @@
370380
buildSettings = {
371381
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
372382
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
383+
CODE_SIGN_ENTITLEMENTS = DestinationsExample/DestinationsExample.entitlements;
384+
CODE_SIGN_IDENTITY = "Apple Development";
373385
CODE_SIGN_STYLE = Automatic;
386+
DEVELOPMENT_TEAM = V8R4668S2H;
374387
INFOPLIST_FILE = DestinationsExample/Info.plist;
375388
LD_RUNPATH_SEARCH_PATHS = (
376389
"$(inherited)",
377390
"@executable_path/Frameworks",
378391
);
379392
PRODUCT_BUNDLE_IDENTIFIER = com.segment.DestinationsExample;
380393
PRODUCT_NAME = "$(TARGET_NAME)";
394+
PROVISIONING_PROFILE_SPECIFIER = "";
381395
SWIFT_VERSION = 5.0;
382396
TARGETED_DEVICE_FAMILY = "1,2";
383397
};
@@ -388,14 +402,18 @@
388402
buildSettings = {
389403
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
390404
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
405+
CODE_SIGN_ENTITLEMENTS = DestinationsExample/DestinationsExample.entitlements;
406+
CODE_SIGN_IDENTITY = "Apple Development";
391407
CODE_SIGN_STYLE = Automatic;
408+
DEVELOPMENT_TEAM = V8R4668S2H;
392409
INFOPLIST_FILE = DestinationsExample/Info.plist;
393410
LD_RUNPATH_SEARCH_PATHS = (
394411
"$(inherited)",
395412
"@executable_path/Frameworks",
396413
);
397414
PRODUCT_BUNDLE_IDENTIFIER = com.segment.DestinationsExample;
398415
PRODUCT_NAME = "$(TARGET_NAME)";
416+
PROVISIONING_PROFILE_SPECIFIER = "";
399417
SWIFT_VERSION = 5.0;
400418
TARGETED_DEVICE_FAMILY = "1,2";
401419
};
@@ -457,6 +475,14 @@
457475
minimumVersion = 8.1.0;
458476
};
459477
};
478+
BA384C9626824F3700AFEA1B /* XCRemoteSwiftPackageReference "AppsFlyerFramework" */ = {
479+
isa = XCRemoteSwiftPackageReference;
480+
repositoryURL = "https://github.com/AppsFlyerSDK/AppsFlyerFramework";
481+
requirement = {
482+
kind = upToNextMajorVersion;
483+
minimumVersion = 6.3.2;
484+
};
485+
};
460486
/* End XCRemoteSwiftPackageReference section */
461487

462488
/* Begin XCSwiftPackageProductDependency section */
@@ -484,6 +510,11 @@
484510
package = 965DC11F2669942800DDF9C7 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
485511
productName = FirebaseAnalytics;
486512
};
513+
BA384C9726824F3700AFEA1B /* AppsFlyerLib */ = {
514+
isa = XCSwiftPackageProductDependency;
515+
package = BA384C9626824F3700AFEA1B /* XCRemoteSwiftPackageReference "AppsFlyerFramework" */;
516+
productName = AppsFlyerLib;
517+
};
487518
/* End XCSwiftPackageProductDependency section */
488519
};
489520
rootObject = 469F7AFC266011690038E773 /* Project object */;

Examples/apps/DestinationsExample/DestinationsExample/AppDelegate.swift

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@ import Segment
1010

1111
@main
1212
class AppDelegate: UIResponder, UIApplicationDelegate {
13-
13+
14+
1415
var analytics: Analytics? = nil
15-
16+
1617
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
1718
// Override point for customization after application launch.
1819

19-
let configuration = Configuration(writeKey: "1234")
20+
let configuration = Configuration(writeKey: "WRITE_KEY")
2021
.trackApplicationLifecycleEvents(true)
21-
.flushInterval(10)
22+
.flushInterval(1)
2223

2324
analytics = Analytics(configuration: configuration)
2425

@@ -36,25 +37,60 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
3637

3738
// Add the Firebase destination plugin
3839
analytics?.add(plugin: FirebaseDestination(name: "Firebase"))
39-
40+
41+
//Add the AppsFlyer destination plugin
42+
analytics?.add(plugin: AppsFlyerDestination(name: "AppsFlyer"))
43+
4044
return true
4145
}
42-
46+
4347
// MARK: UISceneSession Lifecycle
44-
48+
4549
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
4650
// Called when a new scene session is being created.
4751
// Use this method to select a configuration to create the new scene with.
4852
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
4953
}
50-
54+
5155
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
5256
// Called when the user discards a scene session.
5357
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
5458
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
5559
}
56-
57-
60+
61+
// MARK: - Deep Link functionality
62+
63+
// This functionality is needed to forward deep link attribution data with AppsFlyer
64+
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
65+
analytics?.continueUserActivity(userActivity)
66+
return true
67+
}
68+
69+
// This functionality is needed to forward deep link attribution data with AppsFlyer
70+
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
71+
analytics?.continueUserActivity(userActivity)
72+
return true
73+
}
74+
75+
// This functionality is needed to forward deep link attribution data with AppsFlyer
76+
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
77+
analytics?.openURL(url)
78+
return true
79+
}
80+
81+
// This functionality is needed to forward deep link attribution data with AppsFlyer
82+
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
83+
analytics?.openURL(url, options: options)
84+
return true
85+
}
86+
87+
// This functionality is needed to forward deep link attribution data with AppsFlyer
88+
// Report Push Notification attribution data for re-engagements
89+
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [String : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
90+
// this enables remote notifications for various destinations (appsflyer)
91+
analytics?.receivedRemoteNotification(userInfo: userInfo)
92+
}
93+
5894
}
5995

6096
extension UIApplicationDelegate {

Examples/apps/DestinationsExample/DestinationsExample/Base.lproj/Main.storyboard

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
1818
<subviews>
1919
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Event Type" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5DB-ee-sx2">
20-
<rect key="frame" x="20" y="60" width="113.5" height="29"/>
20+
<rect key="frame" x="20" y="16" width="113.5" height="29"/>
2121
<fontDescription key="fontDescription" type="system" pointSize="24"/>
2222
<color key="textColor" red="0.32549019610000002" green="0.74509803919999995" blue="0.58823529409999997" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
2323
<nil key="highlightedColor"/>
2424
</label>
2525
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="qhk-vM-RPB">
26-
<rect key="frame" x="20" y="105" width="374" height="32"/>
26+
<rect key="frame" x="20" y="61" width="440" height="32"/>
2727
<segments>
2828
<segment title="Track"/>
2929
<segment title="Screen"/>
@@ -34,29 +34,29 @@
3434
<color key="tintColor" red="0.32549019610000002" green="0.74509803919999995" blue="0.58823529409999997" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
3535
</segmentedControl>
3636
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Event Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MUh-za-gaw">
37-
<rect key="frame" x="20" y="152" width="92" height="21"/>
37+
<rect key="frame" x="20" y="108" width="92" height="21"/>
3838
<fontDescription key="fontDescription" type="system" pointSize="17"/>
3939
<color key="textColor" red="0.32549019610000002" green="0.74509803919999995" blue="0.58823529409999997" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
4040
<nil key="highlightedColor"/>
4141
</label>
4242
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Name..." textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="4SR-2N-fPO">
43-
<rect key="frame" x="127" y="145.5" width="267" height="34"/>
43+
<rect key="frame" x="127" y="101.5" width="333" height="34"/>
4444
<fontDescription key="fontDescription" type="system" pointSize="14"/>
4545
<textInputTraits key="textInputTraits"/>
4646
</textField>
4747
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1XN-fw-PDy" userLabel="Divider">
48-
<rect key="frame" x="20" y="309.5" width="374" height="2"/>
48+
<rect key="frame" x="20" y="265.5" width="440" height="2"/>
4949
<color key="backgroundColor" red="0.32549019610000002" green="0.74509803919999995" blue="0.58823529409999997" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
5050
<constraints>
5151
<constraint firstAttribute="height" constant="2" id="WWe-PX-Gp8"/>
5252
</constraints>
5353
</view>
5454
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" maximumValue="100" translatesAutoresizingMaskIntoConstraints="NO" id="1Ry-t2-GnA">
55-
<rect key="frame" x="300" y="195.5" width="94" height="32"/>
55+
<rect key="frame" x="366" y="151.5" width="94" height="32"/>
5656
<color key="tintColor" red="0.32549019610000002" green="0.74509803919999995" blue="0.58823529409999997" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
5757
</stepper>
5858
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nRf-b5-W7w">
59-
<rect key="frame" x="157" y="257.5" width="100" height="36"/>
59+
<rect key="frame" x="190" y="213.5" width="100" height="36"/>
6060
<constraints>
6161
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="100" id="1fQ-1x-tVX"/>
6262
<constraint firstAttribute="height" constant="36" id="3Hn-fo-dIv"/>
@@ -69,13 +69,13 @@
6969
</connections>
7070
</button>
7171
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="vyv-SU-C0g">
72-
<rect key="frame" x="20" y="242.5" width="374" height="0.0"/>
72+
<rect key="frame" x="20" y="198.5" width="440" height="0.0"/>
7373
<constraints>
7474
<constraint firstAttribute="height" placeholder="YES" id="q83-lW-xvT"/>
7575
</constraints>
7676
</stackView>
7777
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Properties" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9Dd-dt-9Ni">
78-
<rect key="frame" x="20" y="201" width="265" height="21"/>
78+
<rect key="frame" x="20" y="157" width="331" height="21"/>
7979
<fontDescription key="fontDescription" type="system" pointSize="17"/>
8080
<color key="textColor" red="0.32549019610000002" green="0.74509803919999995" blue="0.58823529409999997" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
8181
<nil key="highlightedColor"/>
@@ -121,7 +121,7 @@
121121
</viewController>
122122
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
123123
</objects>
124-
<point key="canvasLocation" x="108.69565217391305" y="137.94642857142856"/>
124+
<point key="canvasLocation" x="107.5" y="136.875"/>
125125
</scene>
126126
</scenes>
127127
<resources>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>com.apple.developer.associated-domains</key>
6+
<array>
7+
<string>applinks:swifttest.onelink.me</string>
8+
</array>
9+
</dict>
10+
</plist>

Examples/apps/DestinationsExample/DestinationsExample/Info.plist

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,25 @@
1616
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
1717
<key>CFBundleShortVersionString</key>
1818
<string>1.0</string>
19+
<key>CFBundleURLTypes</key>
20+
<array>
21+
<dict>
22+
<key>CFBundleTypeRole</key>
23+
<string>Editor</string>
24+
<key>CFBundleURLName</key>
25+
<string>com.segment.DestinationsExample</string>
26+
<key>CFBundleURLSchemes</key>
27+
<array>
28+
<string>swifttest</string>
29+
</array>
30+
</dict>
31+
</array>
1932
<key>CFBundleVersion</key>
2033
<string>1</string>
2134
<key>LSRequiresIPhoneOS</key>
2235
<true/>
36+
<key>NSUserTrackingUsageDescription</key>
37+
<string>"Test for IDFA"</string>
2338
<key>UIApplicationSceneManifest</key>
2439
<dict>
2540
<key>UIApplicationSupportsMultipleScenes</key>
@@ -41,6 +56,12 @@
4156
</dict>
4257
<key>UIApplicationSupportsIndirectInputEvents</key>
4358
<true/>
59+
<key>UIBackgroundModes</key>
60+
<array>
61+
<string>fetch</string>
62+
<string>processing</string>
63+
<string>remote-notification</string>
64+
</array>
4465
<key>UILaunchStoryboardName</key>
4566
<string>LaunchScreen</string>
4667
<key>UIMainStoryboardFile</key>

Examples/apps/DestinationsExample/DestinationsExample/ViewController.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import UIKit
99
import Segment
10+
import AppsFlyerLib
1011

1112
enum SpecEvent: Int {
1213
case track
@@ -43,7 +44,7 @@ class ViewController: UIViewController {
4344

4445
private var keysFields = [UITextField]()
4546
private var propertiesFields = [UITextField]()
46-
47+
4748
override func viewDidLoad() {
4849
super.viewDidLoad()
4950
// Do any additional setup after loading the view.

0 commit comments

Comments
 (0)