Logging Revenue with StoreKit 1

Learn how to log conversion revenue from StoreKit 1 in-app purchases for iOS 14 and earlier support

ContextSDK supports logging revenue from both StoreKit 1 and StoreKit 2 purchases. This guide covers StoreKit 1 integration, which is essential for apps that need to support iOS 14 and earlier, or are migrating from legacy StoreKit implementations.

Basic StoreKit 1 Integration

Using SKProduct

For basic product information logging, use the SKProduct directly:

Example
// When a purchase completes successfully
func userDidPurchase(product: SKProduct) {
    if let context = ContextManager.recentContext(flowName: "upsell_premium") {
        context.logStoreKit1RevenueOutcome(from: product)
    }
}

Using SKPaymentTransaction

For more detailed transaction tracking, including transaction state and dates:

SKPaymentTransactionObserver
// In your SKPaymentTransactionObserver
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction in transactions {
        switch transaction.transactionState {
        case .purchased:
            handlePurchasedTransaction(transaction)
            queue.finishTransaction(transaction)
        case .restored:
            handleRestoredTransaction(transaction)
            queue.finishTransaction(transaction)
        case .failed:
            handleFailedTransaction(transaction)
            queue.finishTransaction(transaction)
        default:
            break
        }
    }
}

private func handlePurchasedTransaction(_ transaction: SKPaymentTransaction) {
    if let context = ContextManager.recentContext(flowName: "upsell_premium") {
        // Get the product information if available
        let productId = transaction.payment.productIdentifier
        if let product = loadedProducts[productId] {
            // Log with both transaction and product context
            context.logStoreKit1RevenueOutcome(from: transaction, product: product)
        } else {
            // Log with transaction only
            context.logStoreKit1RevenueOutcome(from: transaction)
        }
    }
}

private func handleFailedTransaction(_ transaction: SKPaymentTransaction) {
    if let context = ContextManager.recentContext(flowName: "upsell_premium") {
        context.log(.negative)
    }
}

To emphasize the transaction outcome handling, here are the steps for common transaction states:

1

Purchased

  • Call your purchased handler (e.g., handlePurchasedTransaction).

  • Log revenue using context.logStoreKit1RevenueOutcome(from: transaction, product: product) if you have product info, otherwise context.logStoreKit1RevenueOutcome(from: transaction).

  • Finish the transaction with queue.finishTransaction(transaction).

2

Restored

  • Call your restored handler (e.g., handleRestoredTransaction).

  • Log appropriate outcomes (similar to purchased if you want to attribute restored purchases).

  • Finish the transaction with queue.finishTransaction(transaction).

3

Failed

  • Call your failed handler (e.g., handleFailedTransaction).

  • Log a negative outcome with context.log(.negative) if appropriate.

  • Finish the transaction with queue.finishTransaction(transaction).

Metadata Extracted from StoreKit 1

When using StoreKit 1 products and transactions, ContextSDK automatically extracts the following metadata:

From SKProduct

  • Revenue: product.price

  • Currency: product.priceLocale.currencyCode (defaults to "USD" if unavailable)

  • Revenue Source: Always set to "in_app_purchase"

  • Family Sharing: product.isFamilyShareable (iOS 14.0+ only)

  • Recurrence: "recurring" for subscriptions, "one_time_purchase" for others

  • Subscription Period: Period unit and interval (for subscriptions)

  • Introductory Offers: Price, period, and duration (iOS 11.2+ only)

From SKPaymentTransaction (additional)

  • Transaction ID: transaction.transactionIdentifier

  • Transaction State: "purchased", "failed", "restored", etc.

  • Transaction Date: ISO8601 formatted transaction date

  • Original Transaction ID: For subscription renewals and restores

StoreKit 1 provides less metadata than StoreKit 2, particularly around subscription details and family sharing (which requires iOS 14.0+). The SDK handles these differences automatically and provides sensible defaults.

Was this helpful?