App Conversions Installation for Swift

Send in-app conversion events server-side from your iOS app with Swift, async/await, and Alamofire — complete code examples for Purchase, ViewContent, AddToCart, Lead, CompleteRegistration, and Contact events.

In This Page

Introduction

App Conversions allows mobile app developers to track and measure user interactions and conversions within their mobile apps. It enables developers to send app events directly from their apps to advertising platforms' servers, providing valuable data for ad optimization and tracking the effectiveness of their app marketing campaigns.

With App Conversions, developers can track various app events, such as app installs, app opens, in-app purchases, and other user interactions. These events are sent to advertising platforms, where advertisers can use them to target specific audiences and optimize their ad campaigns for better performance.

Get Started

The following sample packages can be installed for App Conversions in Swift.

Note

Async/await is a modern concurrency feature introduced in Swift 5.5 and above — versions earlier than 5.5 cannot use it!

Imports
import Foundation
import Alamofire
import SwiftyJSON

Extended Device Information

Send device information, such as screen width and height, in your app event call using /{app-id}/activities?extinfo. Values are separated by commas and must be in the order indexed in the /application/activities reference guide. When using extinfo, all values are required.

  • version must be a2 for Android
  • version must be i2 for iOS

Get Mobile Cookies for iOS

We encourage you to associate app events with an advertiser_id. However, for Android devices and iOS devices earlier than iOS 6, you can also use the attribution parameter set to the mobile cookie of the device.

Note

Mobile cookies are not derived from any user or device attributes. These cookies are not persistent and are designed to be refreshed frequently. Do not use mobile cookies for re-targeting ads.

The mobile cookie is created by Facebook iOS apps using CFUUIDCreateString and is a 128-bit UUID string representation. Get both the cookie ID and the IDFA and send them to Facebook as an identifier:

Reading the IDFA
ASIdentifierManager *manager = [ASIdentifierManager sharedManager];
NSString *advertiserID = [[manager advertisingIdentifier] UUIDString];

if (advertiserID) {
    // do stuff
}

Set Up Deduplication

The deduplication mechanism is required to remove duplicate event traffic between the Conversions API integration and all other existing integrations you have with app events, including the SDK and App Events API.

For app events, we apply the same deduplication functionality that exists for web events. The logic leverages event_id and event_name based deduplication (Conversions API and SDK / App Events API events that carry the same event_id). The event_id parameter is an identifier that can uniquely distinguish between similar events. Inaccurate event IDs may cause your conversion to be wrongly deduplicated, further impacting conversion reporting and campaign performance.

Here is an example of how to log a custom event. To do so, pass the name of the event as an AppEvents.Name in the iOS SDK:

Deduplicated event via the iOS SDK
import FBSDKCoreKit

// Generate a unique event ID
let eventId = UUID().uuidString

// Define the custom event_id parameter
let eventIDParameter = AppEvents.ParameterName("event_id")

// Prepare event parameters with AppEvents.ParameterName keys
let parameters: [AppEvents.ParameterName: Any] = [
    eventIDParameter: eventId,
    .currency: "USD",
    .value: 9.99
]

// Log the event with parameters
AppEvents.logEvent(.purchased, parameters: parameters)

// Send the same event_id via Meta Event SDK for server-side tracking
let capiEvent = Event(
    eventName: .purchased,
    eventTime: Date(),
    eventId: eventId, // Use the same eventId
    // Include other necessary properties
)

MetaEventSDK.sendEvent(capiEvent)

Install events

For app install events, there is already a deduplication mechanism that makes sure only one install is attributed in the last 90-day window. We keep the first event and drop the later ones no matter the action source. No extra deduplication is required for install-related events.

Events

Please implement the following events in your app:

  1. Purchase Event
  2. View Content Event
  3. Add To Cart Event
  4. Lead Event
  5. Complete Registration Event
  6. Contact Event

1. Purchase Event

ApiClient.swift — Purchase
class ApiClient {

    // The base URL for the API endpoint
    private let BASE_URL = "https://cpi.ssevt.com/push"
    private let token = "YOUR_BEARER_TOKEN"

    // Function to send a POST request to the API
    func sendPostRequest() async {
        // Define the media type for the request body (application/json)
        let mediaType = "application/json"

        // Create the JSON body
        let jsonBody: [String: Any] = [
            // Required
            "eid": "d290f1ee-6c54-4b01-90e6-d701748f0851", // Order ID or Transaction ID For Purchase Event
            "et": "Purchase", // Event Name
            "ua": "App", // App Static Value
    
            "p": [
                // Required
                "event_time": 1644778428,
                "platform": "ios",
                "os_version": "16.5.1", // iOS version
                "att": 1, // Advertiser Tracking Enabled
                "ate": 1, // Application Tracking Enabled
                "device_model": "Iphone 5,1",
                "currency": "USD",
                "value": 142.54,
                "app_id": "id123456789",
    
                // Optional
                "screen_width": 762,
                "screen_height": 1278,
                "device_timezone": "Europe/London",
                // Add other optional properties here
                // ...
    
                // Required
                "contents": [
                    ["id": "ABC123", "quantity": 1],
                    ["id": "DEF456", "quantity": 1]
                ],
    
                // Required
                "content_type": "product"
            ],
    
            // Advanced Matching Parameters
            "amp": [
                // Required
                "anon_id": "123456abc", // The ID of a person who has installed the app anonymously
                "madid": "7497f910905fb413fe27a64a557778063", // Apple's Advertising Identifier (IDFA)
                // or Google Android's advertising ID
    
                // Optional
                "ph": "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf", // Phone
                "em": "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149", // Email
                "ge": "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111", // Gender
                "db": "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf", // Date Of Birth
                "ct": "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5", // City
                "zp": "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233", // Zip Code
                "cn": "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621"  // Country
            ]
        ]

        // Convert the JSON body to Data
        guard let jsonData = try? JSONSerialization.data(withJSONObject: jsonBody, options: []) else {
            print("Error: Unable to create JSON data")
            return
        }

        // Perform the POST request asynchronously using Alamofire with await
        do {
            var urlRequest = URLRequest(url: URL(string: BASE_URL)!)
            urlRequest.httpMethod = HTTPMethod.post.rawValue
            urlRequest.setValue(mediaType, forHTTPHeaderField: "Content-Type")
            urlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") // Adding Bearer Token
            urlRequest.httpBody = jsonData // Adding JSON data

            let response = try await AF.request(urlRequest).responseJSON()
            let json = JSON(response.value ?? "")
            print("Response: \(json)")
        } catch {
            print("Error: \(error.localizedDescription)")
        }
    }
}

The other events reuse this client

Only the jsonBody changes between events. The sections below show the body for each event — the Alamofire request code stays exactly the same as in the Purchase example.

Parameter List

Advanced Matching Parameters — * required fields
User informationParameterFormatExample
Anonymous ID*anon_idUnique ID — do not hash123456abc
Advertising ID (IDFA / GAID)*madidUnique ID — do not hash7497f910905fb413fe27a64a557778063
E-mailemLowercase + SHA256 hash[email protected]
First namefnLowercase + SHA256 hashjohn
Last namelnLowercase + SHA256 hashdoe
TelephonephOnly numbers, incl. country and area code + SHA256 hash12125357525
GendergeA single lowercase letter, f or m + SHA256 hashf
BirthdaydbOnly numbers: year, month, day + SHA256 hash19910526 for May 26, 1991
CityctLowercase, no spaces + SHA256 hashnewyork
Postal / zip codezpOnly numbers + SHA256 hash34000
CountrycnTwo-letter country code, lowercase + SHA256 hashtr

PII Hashing

Every personal identifier except anon_id and madid must be normalized and SHA256-hashed before sending. Use our PII Hashing guide and live tool to verify your hashes.

2. View Content Event

jsonBody — ViewContent
    let jsonBody: [String: Any] = [
        // Required
        "eid": "d290f1ee-6c54-4b01-90e6-d701748f0851", // Any Unique Identifier
        "et": "ViewContent", // Event Name
        "ua": "App", // App Static Value

        "p": [
            // Required
            "event_time": 1644778428,
            "platform": "ios",
            "os_version": "16.5.1", // iOS version
            "att": 1, // Advertiser Tracking Enabled
            "ate": 1, // Application Tracking Enabled
            "device_model": "Iphone 5,1",
            "currency": "USD",
            "value": 142.54,
            "app_id": "id123456789",

            // Optional
            "screen_width": 762,
            "screen_height": 1278,
            "device_timezone": "Europe/London",
            // Add other optional properties here
            // ...

            // Required
            "contents": [
                ["id": "ABC123", "quantity": 1],
                ["id": "DEF456", "quantity": 1]
            ],

            // Required
            "content_type": "product"
        ],

        // Advanced Matching Parameters
        "amp": [
            // Required
            "anon_id": "123456abc", // The ID of a person who has installed the app anonymously
            "madid": "7497f910905fb413fe27a64a557778063", // Apple's Advertising Identifier (IDFA)
            // or Google Android's advertising ID

            // Optional
            "ph": "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf", // Phone
            "em": "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149", // Email
            "ge": "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111", // Gender
            "db": "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf", // Date Of Birth
            "ct": "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5", // City
            "zp": "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233", // Zip Code
            "cn": "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621"  // Country
        ]
    ]

3. Add To Cart Event

jsonBody — AddToCart
    let jsonBody: [String: Any] = [
        // Required
        "eid": "d290f1ee-6c54-4b01-90e6-d701748f0851", // Any Unique Identifier
        "et": "AddToCart", // Event Name
        "ua": "App", // App Static Value

        "p": [
            // Required
            "event_time": 1644778428,
            "platform": "ios",
            "os_version": "16.5.1", // iOS version
            "att": 1, // Advertiser Tracking Enabled
            "ate": 1, // Application Tracking Enabled
            "device_model": "Iphone 5,1",
            "currency": "USD",
            "value": 142.54,
            "app_id": "id123456789",

            // Optional
            "screen_width": 762,
            "screen_height": 1278,
            "device_timezone": "Europe/London",
            // Add other optional properties here
            // ...

            // Required
            "contents": [
                ["id": "ABC123", "quantity": 1],
                ["id": "DEF456", "quantity": 1]
            ],

            // Required
            "content_type": "product"
        ],

        // Advanced Matching Parameters
        "amp": [
            // Required
            "anon_id": "123456abc", // The ID of a person who has installed the app anonymously
            "madid": "7497f910905fb413fe27a64a557778063", // Apple's Advertising Identifier (IDFA)
            // or Google Android's advertising ID

            // Optional
            "ph": "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf", // Phone
            "em": "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149", // Email
            "ge": "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111", // Gender
            "db": "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf", // Date Of Birth
            "ct": "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5", // City
            "zp": "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233", // Zip Code
            "cn": "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621"  // Country
        ]
    ]

4. Lead Event

jsonBody — Lead
    let jsonBody: [String: Any] = [
        // Required
        "eid": "d290f1ee-6c54-4b01-90e6-d701748f0851", // Any Unique Identifier
        "et": "Lead", // Event Name
        "ua": "App", // App Static Value

        "p": [
            // Required
            "event_time": 1644778428,
            "platform": "ios",
            "os_version": "16.5.1", // iOS version
            "att": 1, // Advertiser Tracking Enabled
            "ate": 1, // Application Tracking Enabled
            "device_model": "Iphone 5,1",
            "app_id": "id123456789",

            // Optional
            "screen_width": 762,
            "screen_height": 1278,
            "device_timezone": "Europe/London"
            // Add other optional properties here
            // ...
        ],

        // Advanced Matching Parameters
        "amp": [
            // Required
            "anon_id": "123456abc", // The ID of a person who has installed the app anonymously
            "madid": "7497f910905fb413fe27a64a557778063", // Apple's Advertising Identifier (IDFA)
            // or Google Android's advertising ID

            // Optional
            "ph": "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf", // Phone
            "em": "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149", // Email
            "ge": "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111", // Gender
            "db": "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf", // Date Of Birth
            "ct": "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5", // City
            "zp": "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233", // Zip Code
            "cn": "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621"  // Country
        ]
    ]

5. Complete Registration Event

jsonBody — CompleteRegistration
    let jsonBody: [String: Any] = [
        // Required
        "eid": "d290f1ee-6c54-4b01-90e6-d701748f0851", // Any Unique Identifier
        "et": "CompleteRegistration", // Event Name
        "ua": "App", // App Static Value

        "p": [
            // Required
            "event_time": 1644778428,
            "platform": "ios",
            "os_version": "16.5.1", // iOS version
            "att": 1, // Advertiser Tracking Enabled
            "ate": 1, // Application Tracking Enabled
            "device_model": "Iphone 5,1",
            "app_id": "id123456789",

            // Optional
            "screen_width": 762,
            "screen_height": 1278,
            "device_timezone": "Europe/London"
            // Add other optional properties here
            // ...
        ],

        // Advanced Matching Parameters
        "amp": [
            // Required
            "anon_id": "123456abc", // The ID of a person who has installed the app anonymously
            "madid": "7497f910905fb413fe27a64a557778063", // Apple's Advertising Identifier (IDFA)
            // or Google Android's advertising ID

            // Optional
            "ph": "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf", // Phone
            "em": "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149", // Email
            "ge": "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111", // Gender
            "db": "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf", // Date Of Birth
            "ct": "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5", // City
            "zp": "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233", // Zip Code
            "cn": "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621"  // Country
        ]
    ]

6. Contact Event

jsonBody — Contact
    let jsonBody: [String: Any] = [
        // Required
        "eid": "d290f1ee-6c54-4b01-90e6-d701748f0851", // Any Unique Identifier
        "et": "Contact", // Event Name
        "ua": "App", // App Static Value

        "p": [
            // Required
            "event_time": 1644778428,
            "platform": "ios",
            "os_version": "16.5.1", // iOS version
            "att": 1, // Advertiser Tracking Enabled
            "ate": 1, // Application Tracking Enabled
            "device_model": "Iphone 5,1",
            "app_id": "id123456789",

            // Optional
            "screen_width": 762,
            "screen_height": 1278,
            "device_timezone": "Europe/London"
            // Add other optional properties here
            // ...
        ],

        // Advanced Matching Parameters
        "amp": [
            // Required
            "anon_id": "123456abc", // The ID of a person who has installed the app anonymously
            "madid": "7497f910905fb413fe27a64a557778063", // Apple's Advertising Identifier (IDFA)
            // or Google Android's advertising ID

            // Optional
            "ph": "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf", // Phone
            "em": "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149", // Email
            "ge": "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111", // Gender
            "db": "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf", // Date Of Birth
            "ct": "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5", // City
            "zp": "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233", // Zip Code
            "cn": "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621"  // Country
        ]
    ]