Enable order signals in an iOS app

The order signal captures when a user completes a transaction in your app - for example, a retail purchase, a flight booking or an insurance application. It is essential for tracking conversions and triggering post-purchase campaigns. In Connect, the signal enables segmentation by order ID, value, product and product category.

Availability: Pro, Premium and Ultimate

Languages: Swift and Objective-C


Implementation considerations

When to fire the signal

Fire the order signal after the order is confirmed by your backend, not when the user taps the purchase button. At that point you have the order ID and all the data needed to populate the signal fields. If your success flow clears the cart, capture the line items before doing so - the item data needed for orderedItems will no longer be available after the cart is cleared.

Ordered items

Each item in the order is represented as a [String: Any] dictionary inside an array. Pass the array as the value of orderedItems in the signal dictionary. If orderedItems fails validation - for example, due to a missing required item field - the entire signal is discarded.

Contact mapping

Include the audience field to attribute this signal to a contact in Connect. See How behavior signals update Connect data for identifier formats and contact resolution details.


Configuration

Before adding behavior signals, integrate the Connect SDK into your app. See the guide for your development language: Swift or Objective-C.

Method

  func logSignal(_ data: [String: Any]?) -> Bool

Sends the signal to the Acoustic Connect endpoint. Initialize the Connect SDK before calling this method using ConnectSDK.shared.enable(with:).

Pass order-level fields as a flat [String: Any] dictionary. Pass orderedItems as an array of item dictionaries.

Signal fields

Order-level required

FieldTypeDescription
orderIdStringUnique order identifier returned by your backend
signalTypeStringSignal type. Value: "order".

Order-level optional

FieldTypeDescription
audience[String: Any]Key-value pairs for contact mapping. Keys must match contact attribute names exactly as they appear in Connect, including capitalization and spacing.
categoryStringSignal category. Value: "Behavior".
currencyStringISO 4217 currency code (for example, "USD", "EUR"). Defaults to the currency set for your Connect subscription.
descriptionStringA description of the signal
nameStringA label to differentiate this signal from others (for example, "order from iOS app"). Max 256 characters
orderDiscountNumberTotal discount applied to the order
orderedItems[[String: Any]]Array of ordered items. Each item is a [String: Any] dictionary - see item-level fields below.
orderShippingHandlingNumberShipping and handling cost
orderSubtotalNumberSubtotal amount before tax and shipping
orderTaxNumberTax amount
orderValueNumberTotal order value including tax and shipping

Item-level required

FieldTypeDescription
itemQuantityNumberQuantity of this product purchased
productIdStringUnique product identifier (may match SKU)
productNameStringName of the product
unitPriceNumberPrice the customer paid for one unit

Item-level optional

FieldTypeDescription
discountNumberDiscount amount per unit
productCategoryStringProduct category from your catalog
productDescriptionStringDescription of the product
promotionIdStringID from a marketing campaign that influenced the purchase
shoppingCartUrlStringURL or deep link to the shopping cart
virtualCategoryStringCategory based on navigation path (for example, "New arrivals", "Sale")

Things to know

  • Number fields accept native Swift numeric types (Int, Double, NSDecimalNumber).

  • Pass orderedItems as a [[String: Any]] array. If orderedItems fails validation, the entire signal is discarded.

  • If a required field is missing or invalid, the entire signal is discarded. For fields that don't apply to your business, use a placeholder value.

Basic example

import Connect

let item: [String: Any] = [
    "productId": "SKU-12345",
    "productName": "Wireless Headphones",
    "itemQuantity": 1,
    "unitPrice": 299.99
]

ConnectCustomEvent.sharedInstance().logSignal([
    "signalType": "order",
    "orderId": "ORD-98765",
    "orderValue": 299.99,
    "currency": "USD",
    "orderedItems": [item]
])
#import <Connect/Connect.h>

NSDictionary *item = @{
    @"productId": @"SKU-12345",
    @"productName": @"Wireless Headphones",
    @"itemQuantity": @1,
    @"unitPrice": @299.99
};

[[ConnectCustomEvent sharedInstance] logSignal:@{
    @"signalType": @"order",
    @"orderId": @"ORD-98765",
    @"orderValue": @299.99,
    @"currency": @"USD",
    @"orderedItems": @[item]
}];

Complete example

This example fires an order signal from the confirmation screen after the backend confirms the order. It includes multiple ordered items, order totals and optional contact mapping.

import Connect

private func sendOrderSignal(orderId: String, items: [CartLineItem], total: NSDecimalNumber) {
    // Build ordered items - one dictionary per line item
    let orderedItems: [[String: Any]] = items.map { item in
        var orderedItem: [String: Any] = [
            "productId": item.product.id,
            "productName": item.product.name,
            "itemQuantity": item.quantity,
            "unitPrice": item.product.price.doubleValue,
            "productCategory": item.product.categoryName,
            "currency": "USD"
        ]
        return orderedItem
    }

    var signal: [String: Any] = [
        "signalType": "order",
        "orderId": orderId,
        "orderValue": total.doubleValue,
        "currency": "USD",
        "orderedItems": orderedItems
    ]

    var audience: [String: Any] = [:]
    if let email = UserSession.shared.email {
        audience["Email Address"] = email
    }
    if !audience.isEmpty {
        signal["audience"] = audience
    }

    let accepted = ConnectCustomEvent.sharedInstance().logSignal(signal)
    NSLog("[Connect] order signal accepted: \(accepted)")
}
#import <Connect/Connect.h>

- (void)sendOrderSignalWithOrderId:(NSString *)orderId
                             items:(NSArray *)items
                             total:(NSDecimalNumber *)total {
    NSMutableArray *orderedItems = [NSMutableArray array];
    for (CartLineItem *item in items) {
        [orderedItems addObject:@{
            @"productId": item.product.id,
            @"productName": item.product.name,
            @"itemQuantity": @(item.quantity),
            @"unitPrice": @(item.product.price.doubleValue),
            @"productCategory": item.product.categoryName,
            @"currency": @"USD"
        }];
    }

    NSMutableDictionary *signal = [@{
        @"signalType": @"order",
        @"orderId": orderId,
        @"orderValue": @(total.doubleValue),
        @"currency": @"USD",
        @"orderedItems": orderedItems
    } mutableCopy];

    NSMutableDictionary *audience = [NSMutableDictionary dictionary];
    if ([[UserSession shared] email]) {
        audience[@"Email Address"] = [[UserSession shared] email];
    }
    if (audience.count > 0) {
        signal[@"audience"] = audience;
    }

    BOOL accepted = [[ConnectCustomEvent sharedInstance] logSignal:signal];
    NSLog(@"[Connect] order signal accepted: %@", accepted ? @"true" : @"false");
}

Call the method before clearing the cart - once the cart is cleared, the line item data is no longer available.


Verification

After running the app and completing checkout, check the Xcode console for:

[Connect] order signal accepted: true

The false value means the SDK rejected the call - see Troubleshooting below. Once the console confirms acceptance, verify the signal is available in Connect. Confirm orderId and orderedItems match the values from the completed order.


Troubleshooting

Signal not appearing in Connect?

  • Confirm the Connect SDK is initialized before any signal calls. See Method.
  • Capture the return value and check that it is true: let accepted = ConnectCustomEvent.sharedInstance().logSignal(signal). A false return indicates the SDK rejected the call.
  • Verify the appKey and postURL match the Connect org you're checking.

Signal marked as invalid in Connect?

  • Confirm the required order-level fields are present: signalType and orderId.
  • Confirm each item in orderedItems has all required fields: productId, productName, itemQuantity, unitPrice.

Contact not created or updated?

  • Verify attribute key names in audience match exactly how they appear in Connect - including capitalization and spacing.

Order items missing from the signal?

  • Confirm orderedItems is populated before the cart is cleared.
  • Check that the array is not empty - an empty orderedItems array may be treated as invalid.

Related pages



Did this page help you?