SDK Integration

This guide describes how to add Apphud SDK to your iOS app.

Requirements

Apphud SDK requires minimum iOS 11.2 and Xcode 10 and Swift version 5.0.

Installation

Apphud SDK can be installed via CocoaPods, Carthage, Swift Package Manager or manually.

Install via CocoaPods

Add the following line to your Podfile:

pod 'ApphudSDK'

In Objective-C project make sure use_frameworks! is added in your Podfile.

Install via Carthage

Add the following line to your Cartfile:

github "apphud/ApphudSDK"

And then run in the Terminal:

carthage update

Install via Swift Package Manager

Add package dependency with the following URL:

https://github.com/apphud/ApphudSDK

Manual Installation

Copy all files from ApphudSDK folder to your project from this link.

Configure Apphud SDK

Integration process consists of following parts:

Initialize SDK

To initialize Apphud SDK you will need SDK Token. It is a unique identifier of your Apphud application. You can get it in your Apphud application settings under General tab.

Basic initialization looks like this:

Swift
Objective-C
Swift
import ApphudSDK
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Apphud.setFinishAllTransactions() // Add if using SDK in purchase mode
Apphud.start(apiKey: "YOUR_SDK_TOKEN")
// the rest of your code
return true
}
Objective-C
#import <ApphudSDK-Swift.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[Apphud setFinishAllTransactions]; // Add if using SDK in purchase mode
// pass nil to userID to let Apphud generate it's own userID.
[Apphud startWithApiKey:@"YOUR_SDK_TOKEN" userID:nil];
// the rest of your code
return YES;
}

If you are planning to use Apphud SDK in purchase mode, i.e. purchase products using Apphud SDK methods, you will need to add Apphud.setFinishAllTransactions()before initialising SDK.

If you are planning to use Apphud SDK in observer mode, i.e. purchase products using your own code, you don't need to callApphud.setFinishAllTransactions()

Configure Push Notifications

Configuring push notifications is highly recommended in order to use Rules – a powerful feature that lets you increase your app revenue by automatically offering a discount to a user at the specified moment.

Handle In-App Purchases

If you have a live app and already implemented purchasing logic, it's not necessary to rewrite your purchase code with Apphud methods. Apphud SDK will still automatically track all purchases in your app.

Apphud SDK provides a set of methods to manage subscriptions and non-renewing purchases. All these methods can be used regardless of how you purchased the product (via Apphud SDK or your existing code).

Get StoreKit Products

Apphud automatically fetches SKProduct objects upon launch. Make sure products identifiers are added in Apphud products. To get your products call:

Swift
Objective-C
Swift
Apphud.products()
Objective-C
[Apphud products];

When products are fetched from the App Store you will also receive a notification from Notification Center along with Apphud delegate method call and a callback block, if set. So use whatever you want.

You can also force refresh products by calling refreshStoreKitProducts method. See Apphud.swift file for details. Use this method only as a fallback.

Make a Purchase

To make a purchase call:

Swift
Objective-C
Swift
Apphud.purchase(product) { result in
if let subscription = result.subscription, subscription.isActive(){
// has active subscription
} else if let purchase = result.nonRenewingPurchase, purchase.isActive(){
// has active non-renewing purchase
} else {
// handle error or check transaction status.
}
}
Objective-C
[Apphud purchase:product callback:^(ApphudPurchaseResult * result) {
if (result.subcription.isActive){
// has active subscription
} else if (result.nonRenewingPurchase.isActive){
// has active non-renewing purchase
} else {
// handle error or check transaction status
}
}];

This method will return an ApphudPurchaseResult object, which contains subscription model with all info about your subscription. ApphudPurchaseResult may also contain transaction, error and nonRenewingPurchase objects in case user purchased non-renewing purchase. See ApphudPurchaseResult.swift and ApphudSubscription.swift files for details.

You can also read In-App Purchase Testing Tips.

Check Subscription Status

Swift
Objective-C
Swift
Apphud.hasActiveSubscription()
Objective-C
[Apphud hasActiveSubscription];

Returns true if user has active subscription. Use this method to determine whether to unlock premium functionality to the user.

Get Subscription Details

To get subscription object (which contains expiration date, autorenewal status, etc.) use the following method:

Swift
Objective-C
Swift
Apphud.subscription()
Objective-C
[Apphud subscription];

See ApphudSubscription.swift file for details.

Check Non-renewing Purchase Status

Use this method to check whether the user has purchased in-app purchase and it's not refunded. Returns false if was never purchased or is refunded.

Swift
Objective-C
Swift
Apphud.isNonRenewingPurchaseActive(productIdentifier: "productID")
Objective-C
[Apphud isNonRenewingPurchaseActiveWithProductIdentifier:@"producID"];

Get Non-renewing Purchase Details

To get non-renewing purchases, which contain purchase date, product identifier and cancellation date, use the following method:

Swift
Objective-C
Swift
Apphud.nonRenewingPurchases()
Objective-C
[Apphud nonRenewingPurchases];

It will return array of all non-renewing in-app purchases user has ever purchased. In-app purchases are sorted by purchase date.

Restore Purchases

If your app doesn't have a login system, which identifies a premium user by his credentials, then you need a "restore" mechanism. If you already have a "restore purchases" mechanism by calling SKPaymentQueue.default().restoreCompletedTransactions(), then you have nothing to worry about: Apphud SDK will automatically intercept and send the latest App Store Receipt to Apphud servers when your restoration is completed. However, better to call our restore method from SDK:

Swift
Objective-C
Swift
Apphud.restorePurchases{ subscriptions, purchases, error in
if Apphud.hasActiveSubscription(){
// has active subscription
} else {
// no active subscription found, check non-renewing purchases or error
}
}
Objective-C
[Apphud restorePurchasesWithCallback:^(NSArray<ApphudSubscription *> * _Nullable subscriptions, NSArray *purchases, NSError * _Nullable error) {
if (Apphud.hasActiveSubscription){
// has active subscription
} else {
// no active subscription found, check non-renewing purchases or error
}
}];

Basically it just sends App Store Receipt to Apphud and returns subscriptions (or nil, if subscriptions are never purchased), non-renewing purchases (or nil, if there are no any) and an optional error.

Handle Promoted In-App Purchases

Do not get confused with Promotional Offers! Promoted in-app purchases are the ones that appear in the App Store page.

If you have in-app purchases that can be purchased directly from the App Store, you should implement a logic to continue a payment in the app.

To continue an in-app purchase transaction initiated from the App Store page, please implement the following ApphudDelegate method:

Swift
Objective-C
Swift
func apphudShouldStartAppStoreDirectPurchase(_ product: SKProduct) -> ((ApphudPurchaseResult) -> Void) {
// manage your UI here, show a progress hud, etc.
let callback : ((ApphudPurchaseResult) -> Void) = { result in
// check the result, hide a progress hud, etc.
}
return callback
}
Objective-C
- (void (^)(ApphudPurchaseResult * _Nonnull))apphudShouldStartAppStoreDirectPurchase:(SKProduct *)product {
// manage your UI here, show a progress hud, etc.
return ^(ApphudPurchaseResult * _Nonnull result) {
// check the result, hide a progress hud, etc.
};
}

You must return a callback block which will be called when a payment is finished. If you don't implement this method or return nil then a payment will not start; you can also save the product and return nil to initiate a payment later by yourself. You can also read Apple documentation for details.

Migrate Existing Paying Users

If you already have a live app with paying users and you want Apphud to track their subscriptions and non-renewing purchases, you should import their App Store receipts into Apphud. Apphud SDK doesn't automatically submit App Store receipts of your existing paying users. Run this code at launch of your app:

Swift
Swift
// hasPurchases - is your own boolean value indicating that current user is paying user.
if hasPurchases {
Apphud.migratePurchasesIfNeeded {_, _, _ in}
}

Set up Analytics Integrations (iOS part)

If you want to pass subscription events to your analytics services, such as Amplitude or Mixpanel, you need to match user identifiers between Apphud and your analytics.

You don't need to match identifiers in case of AppsFlyer or Branch integration. Check integration guide to your attribution platform.

You can see more code samples here. There are two ways to match user identifiers:

Initialize Apphud first, then initialize your analytics with Apphud User ID:

Swift
Objective-C
Swift
Apphud.start(apiKey: "YOUR_SDK_TOKEN")
Apphud.setDelegate(self)
// Amplitude SDK
Amplitude.instance()?.initializeApiKey("YOUR_AMPLITUDE_API_KEY", userId: Apphud.userID())
// Mixpanel SDK
Mixpanel.initialize(token: "mixpanel_token")
Mixpanel.mainInstance().identify(distinctId: Apphud.userID())
Objective-C
[Apphud startWithApiKey:@"YOUR_SDK_TOKEN" userID:nil];
[Apphud setDelegate:self];
// Amplitude SDK
[Amplitude.instance initializeApiKey:@"AMPLITUDE_API_KEY" userId:Apphud.userID];
// Mixpanel SDK
[Mixpanel sharedInstanceWithToken:@"MIXPANEL_TOKEN"];
[Mixpanel.sharedInstance identify:Apphud.userID];

However, userID may change if user has restored purchases from his another device. You need to implement the following delegate method of ApphudDelegate:

Swift
Objective-C
Swift
func apphudDidChangeUserID(_ userID: String) {
// Amplitude SDK
Amplitude.instance()?.setUserId(userID)
// Mixpanel SDK
Mixpanel.mainInstance().identify(distinctId: userID)
}
Objective-C
- (void)apphudDidChangeUserID:(NSString *)userID {
// Amplitude SDK
[Amplitude.instance setUserId:userID];
// Mixpanel SDK
[Mixpanel.sharedInstance identify:userID];
}

Match user identifiers by your custom userID

Only do this if you are sure that your custom userID explicitly identifies users across their multiple devices. For example, if you have a login system with unique username and password, you can pass username as user ID. The only requirement is to update Apphud userID and your analytics userID simultaneously.

Note: Amplitude requires user id length to be minimum 5 characters.

This can be done at app launch:

Swift
Objective-C
Swift
// Initialize Apphud and analytics with your own user id
Apphud.start(apiKey: "YOUR_SDK_TOKEN", userID: "YOUR_OWN_USER_ID")
// Amplitude SDK
Amplitude.instance()?.initializeApiKey("YOUR_AMPLITUDE_API_KEY", userId: "YOUR_OWN_USER_ID")
// Mixpanel SDK
Mixpanel.initialize(token: "mixpanel_token")
Mixpanel.mainInstance().identify(distinctId: "YOUR_OWN_USER_ID")
Objective-C
// Initialize Apphud and analytics with your own user id
[Apphud startWithApiKey:@"YOUR_SDK_TOKEN" userID:@"YOUR_OWN_USER_ID"];
// Amplitude SDK
[Amplitude.instance initializeApiKey:@"AMPLITUDE_API_KEY" userId:@"YOUR_OWN_USER_ID"];
// Mixpanel SDK
[Mixpanel sharedInstanceWithToken:@"MIXPANEL_TOKEN"];
[Mixpanel.sharedInstance identify:@"YOUR_OWN_USER_ID"];

Or you can change userID later. For example, after user logs in:

Swift
Objective-C
Swift
// After user logged in:
Apphud.updateUserID("YOUR_OWN_USER_ID")
Amplitude.instance()?.setUserId("YOUR_OWN_USER_ID")
Mixpanel.mainInstance().identify(distinctId: "YOUR_OWN_USER_ID")
Objective-C
// After user logged in:
[Apphud updateUserID:@"YOUR_OWN_USER_ID"];
[Amplitude.instance setUserId:@"YOUR_OWN_USER_ID"];
[Mixpanel.sharedInstance identify:@"YOUR_OWN_USER_ID"];

Testing Integrations in Sandbox

To test integrations, ensure that test credentials are provided and make a sandbox in-app purchase.

Apphud will send all subscription events of current user to your test analytics, if test credentials are set in integration settings.

Sandbox events will never be sent to your production integrations. If test credentials are not provided, sandbox events will not be sent anywhere.

You can also click on "Send Test Event" near the integration's "..." button. This feature is available only for some Integrations.

Other

User Eligibility for Introductory Offer

You can use Apphud to determine if user is eligible for introductory offer:

Swift
Objective-C
Swift
// Check eligibility for introductory offer
Apphud.checkEligibilityForIntroductoryOffer(product: myProduct) { result in
// handle result
}
// Check eligibility for multiple products at one call
Apphud.checkEligibilitiesForIntroductoryOffers(products: products) { resultDict in
// handle result
}
Objective-C
// Check eligibility for introductory offer
[Apphud checkEligibilityForIntroductoryOfferWithProduct:myProduct callback:^(BOOL eligible) {
// handle result
}];
// Check eligibility for multiple products at one call
[Apphud checkEligibilitiesForIntroductoryOffersWithProducts:productsArray callback:^(NSDictionary * resultDict) {
// handle result
}];

User Eligibility for Promotional Offer

You can also use Apphud to determine if user is eligible for promotional offer:

Swift
Objective-C
Swift
// Check eligibility for promotional offer
Apphud.checkEligibilityForPromotionalOffer(product: myProduct) { result in
// handle result
}
// Check eligibility for multiple products at one call
Apphud.checkEligibilitiesForPromotionalOffers(products: products) { resultDict in
// handle result
}
Objective-C
// Check eligibility for promotional offer
[Apphud checkEligibilityForPromotionalOfferWithProduct:myProduct callback:^(BOOL eligible) {
// handle result
}];
// Check eligibility for multiple products at one call
[Apphud checkEligibilitiesForPromotionalOffersWithProducts:productsArray callback:^(NSDictionary * resultDict) {
// handle result
}];