Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is There A Way To Get Notified When Someone Makes An In-App Purchase?

I'd like to be notified when someone makes an In-App Purchase in my App rather than wait until the next day to check iTunes Connect to see wether or not I had any sales.

Does anyone know of a way to do this? If not, it would be really cool!

Thanks

like image 485
Creagen Avatar asked Aug 15 '15 05:08

Creagen


2 Answers

Track StoreKit Purchase Events

When a purchase takes place, send yourself a datapoint (Track here...)

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transation in transactions {
        switch transation.transactionState {

            case .purchased:
                queue.finishTransaction(transation)
                // Track here...

            case .purchasing: break
            case .restored: break
            case .deferred: break
            case .failed: break
        }
    }
}

Leverage Libraries

Use analytics. Replace the // Track here... comment above by any of the blocks below. Non exhaustive list in alphabetical order:

Accengage

NSString *currencyCode = [<SKProduct.priceLocale>
                          objectForKey:NSLocaleCurrencyCode];
BMA4SPurchasedItem* item =
    [BMA4SPurchasedItem itemWithId(t.payment.productIdentifier)
        label:t.payment.productName
        category:<product.type>
        price:@(<SKProduct.price>)
        quantity:t.payment.quantity
];
[BMA4STracker trackPurchaseWithId:transaction.identifier
                         currency:currencyCode
                            items:@[item]];

Branch

NSDictionary *state = @{ 
    @"itemId": @(t.payment.productIdentifier),
    @"price": <SKProduct.price>, 
    @"itemName": <SKProduct.name>, 
    @"currency":currencyCode };
[[Branch getInstance] userCompletedAction:@"purchase" withState:state];

Fabric (Crashlytics)

NSString *currencyCode = [<SKProduct.priceLocale>
                          objectForKey:NSLocaleCurrencyCode];
[Answers logPurchaseWithPrice:<SKProduct.price>
                     currency:currencyCode
                      success:@YES
                     itemName:<product name>
                     itemType:@"Purchase"
                       itemId:@(t.payment.productIdentifier)
             customAttributes:@{}];

FlightRecorder

FlightRecorder.sharedInstance().trackEventWithCategory(
    "Actions",
    action: "Purchase",
    label: "productIdentifier",
    value: t.payment.productIdentifier)

Flurry Analytics

let properties = ["productIdentifier":t.payment.productIdentifier]
Flurry.logEvent("Purchase", withParameters: properties)

Google Analytics

#import "GAI.h"
#import "GAIDictionaryBuilder.h"

id<GAITracker> tracker = [[GAI sharedInstance] defaultTracker];
NSString *currencyCode = [<SKProduct.priceLocale>
                          objectForKey:NSLocaleCurrencyCode];
[tracker send:[[GAIDictionaryBuilder
                createItemWithTransactionId:transactionIdentifier
                name:<product.localizedTitle>
                sku:t.payment.productIdentifier
                category:@"Purchase"
                price:<SKProduct.price>
                quantity:@(t.payment.quantity)
                currencyCode:currencyCode]
               build]];

See In-app purchase tracking with Google Analytics iOS SDK.

Heap Analytics

[Heap track:@"Purchase"
    withProperties:@{@"productIdentifier":@(t.payment.productIdentifier)}
];

Mixpanel Analytics(*)

Mixpanel.sharedInstance().track("Purchased",
                                properties: ["productIdentifier":transation.payment.productIdentifier])
     properties:@{@"productIdentifier":@(t.payment.productIdentifier)};

(*) Provides support for WiFi reporting (allows to postpone all reporting until WiFi network is available, as to not use cellular data). See mixpanelWillFlush below.

Parse.com

NSDictionary *dimensions =
    @{@"productIdentifier":@(t.payment.productIdentifier)};
[PFAnalytics trackEvent:@“Purchase” dimensions:dimensions];

Send an email from a server

POST purchase to a URL, and have in turn the server send you a mail or other notification.

iOS implementation using URLSession:

if let url = URL(string: "https://<yoursite>/php/purchase.php") {
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody =
        "{\"productIdentifier\":\"\(transaction.payment.productIdentifier)\"}"
        .data(using: .utf8)
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    let task = URLSession.shared.dataTask(with: request as URLRequest,
                                          completionHandler: {_,_,_ in })
    task.resume()
}

purchase.php email sender:

<?php
try {
    header('Content-type: application/json');
    $to = '[email protected]';
    $subject = 'Purchase';
    $message = $_POST['productIdentifier'];
    $headers = "From: " . $to . "\n";
    @mail($to, $subject, $message, $headers)
} catch (Exception $e) {}
?>

► Find this solution on GitHub and additional details on Swift Recipes.

like image 176
SwiftArchitect Avatar answered Nov 12 '22 14:11

SwiftArchitect


Fabric (formerly Crashlytics), in addition to being a fantastic (and free) crash logging system, also includes a component called Answers, which tracks usage stats in real time:

enter image description here

Recently, they added the ability to add custom event tracking, so it's a simple matter to add a "Product Purchased" event to you app. Adding Crashlytics to your app takes seconds (and they walk you through the process), and adding a custom event like that takes a single line of code. From then on, you'll be able to track all sorts of info about purchases made, number of users, and any other metadata you want to record, all with a delay of about 3 seconds.

I've been using Crashlytics for years (actually based on a StackOverflow question of my own), and I CANNOT recommend it highly enough. It's free, easy, and incredibly effective.

like image 10
Nerrolken Avatar answered Nov 12 '22 13:11

Nerrolken