> ## Documentation Index
> Fetch the complete documentation index at: https://moengage-sdk-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Transactional Live Activity

# Overview

[iOS Live Activities](https://developer.apple.com/design/human-interface-guidelines/live-activities) display your app's most current data as real-time, interactive updates on the iPhone Lock Screen and in the [Dynamic Island](https://support.apple.com/en-in/guide/iphone/iph28f50d10d/ios). Transactional Live Activities are specifically designed for unique, user-specific events such as order tracking, ride-hailing updates, or personalized transaction states.

<Info>
  **Information**

  Live Activities and push notifications have different user permission models. By default, Live Activities are enabled for an app. Users can manage permissions for each app individually in their device settings.
</Info>

<Note>
  **Prerequisites**

  Before you begin, ensure your project and accounts are configured correctly.

  1. **Apple Developer Account Configuration**:
     * In your Apple Developer account, navigate to **Certificates**, **IDs & Profiles** > **Identifiers** and select your app's identifier.
     * Under the **Capabilities** tab, ensure that **Push Notifications** checkbox is selected. This is mandatory for the Apple Push Notification service (APNs) to deliver activity updates.
     * **APNs Authentication Key**: To authorize MoEngage to send push notifications on your behalf, you must configure an APNs Authentication Key. For detailed steps on how to upload the .p8 file to the MoEngage dashboard, please refer to the [documentation](/developer-guide/ios-sdk/push/basic/apns-authentication-key) on APNs Authentication Key.
  2. **SDK version:** MoEngage iOS SDK 10.09.0 or higher is required to support Transactional Live Activities.
  3. **MoEngage Live Activity Module**: The MoEngageLiveActivity module is required to handle transactional updates.
  4. **Xcode and iOS Version**:
     * **Xcode**: Use Xcode 14.1 or later.
     * **iOS Target**: Your Live Activity must target iOS 18 and later.
</Note>

# Implementing a Transactional Live Activity

This section covers the client-side setup required within your Xcode project for Transactional Live Activities.

## Step 1: Add a Widget Extension

1. In Xcode, navigate to **File** > **New** > **Target**.
2. Select **Widget Extension** and click **Next**.

   <Frame>
     <img src="https://mintcdn.com/moengage-sdk-docs/kHOLru4lDSgquAXU/images/transla1.png?fit=max&auto=format&n=kHOLru4lDSgquAXU&q=85&s=8eb69cbe2a29e4cf68b90df1e8436693" alt="Transla1" width="1910" height="1364" data-path="images/transla1.png" />
   </Frame>
3. Enter a product name for your widget.
4. Select the **Include Live Activities** checkbox.

   <Frame>
     <img src="https://mintcdn.com/moengage-sdk-docs/kHOLru4lDSgquAXU/images/transla2.png?fit=max&auto=format&n=kHOLru4lDSgquAXU&q=85&s=900dc066ed9be3ff2e6fcc0856b2bb70" alt="Transla2" width="1910" height="1362" data-path="images/transla2.png" />
   </Frame>
5. Click **Finish**.

## Step 2: Configure App's Info.plist

Add Live Activities support to your main app's Info.plist.

<CodeGroup>
  ```xml XML wrap theme={"theme":{"light":"github-light","dark":"github-dark"}}
  <key>NSSupportsLiveActivities</key>
  <true/>
  ```
</CodeGroup>

## Step 3: MoEngageLiveActivity integration

<Info>
  **Information**

  To integrate the MoEngageLiveActivity framework, ensure you are using MoEngage iOS SDK version 10.09.0 or higher.
</Info>

#### **Install using Swift Package Manager (Recommended )**

The MoEngageLiveActivity framework is supported via SPM from SDK version 10.09.0. To integrate, use the GitHub URL [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) and set the branch as master or the required version.

#### **Install using CocoaPod**

<Info>
  **Information**

  CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more info on CocoaPods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
</Info>

To integrate the MoEngageLiveActivity framework, add the following dependency to your Podfile:

<CodeGroup>
  ```ruby Ruby wrap theme={"theme":{"light":"github-light","dark":"github-dark"}}
  target 'MoETest' do
    use_frameworks!

    # Pods for app target
    pod 'MoEngage-iOS-SDK' # specify version constraint
    pod 'MoEngage-iOS-SDK/LiveActivity'

    target 'LiveActivity' do
      use_frameworks!
      inherit! :search_paths
      # Pods for live activity extension target
      pod 'MoEngage-iOS-SDK/LiveActivity'
    end
  end
  ```
</CodeGroup>

## Step 4: Define the Live Activity Attributes

In the Swift file generated for your widget extension, define the data structure for your Transactional Live Activity (e.g., a Food Delivery order).

1. Configure ActivityAttributes: Create a struct that conforms to [ActivityAttributes](https://developer.apple.com/documentation/activitykit/activityattributes). This struct will contain:
   * **Static Data**: Attributes that are set once and do not change (e.g., Order Number).
   * **ContentState**: A nested struct for dynamic data that will be updated in real-time (e.g., Delivery Status).

     <CodeGroup>
       ```swift Swift wrap theme={"theme":{"light":"github-light","dark":"github-dark"}}
       import Foundation
       import ActivityKit
       import WidgetKit
       import SwiftUI

       struct FoodOrderAttributes: ActivityAttributes {
           public struct ContentState: Codable, Hashable {
               // Dynamic stateful properties about your order go here!
               var status: String // e.g., "Out for Delivery"
               var estimatedMinutes: Int
           }

           // Fixed non-changing properties about your order go here!
           var orderNumber: String
           var restaurantName: String
       }
       ```
     </CodeGroup>
2. When creating ActivityConfiguration, use *MoEngageTransactionActivityAttributes\<FoodOrderAttributes>* instead of FoodOrderAttributes as your ActivityAttributes type for transactional support.
3. Track widget clicks by configuring the deeplink and widget ID with the moengageWidgetClickURL API.

   <CodeGroup>
     ```swift Swift wrap theme={"theme":{"light":"github-light","dark":"github-dark"}}
     import ActivityKit
     import WidgetKit
     import SwiftUI
     import MoEngageLiveActivity

     struct FoodOrderWidget: Widget {
         var body: some WidgetConfiguration {
             ActivityConfiguration(for: MoEngageTransactionActivityAttributes<FoodOrderAttributes>.self) { context in
                 // Lock screen/banner UI goes here
                 VStack(spacing: 12) {
                     Text(context.attributes.appAttributes.restaurantName)
                     Text(context.state.appContent.status)
                 }
                 .moengageWidgetClickURL(URL(string: "moeapp://order-tracking"), context: context, widgetId: 2)
                 
             } dynamicIsland: { context in
                 DynamicIsland {
                     // Expanded UI goes here
                 } compactLeading: {
                     Text("Preparing")
                 } compactTrailing: {
                     Text("\(context.state.appContent.estimatedMinutes)m")
                 } minimal: {
                     Text("Preparing")
                 }
                 .moengageWidgetClickURL(URL(string: "moeapp://order-tracking"), context: context, widgetId: 1)
             }
         }
     }
     ```
   </CodeGroup>
4. **Ensure Target Membership**: Make your ActivityAttributes struct accessible to your main app target.
   1. Select the Swift file where you defined your ActivityAttributes.
   2. Open the **File Inspector** (Option + Command + 1).
   3. In the **Target Membership** section, check the box for your main app target.

## Step 5: Monitor Live Activities

Call the `monitorLiveActivities` method to register the `ActivityAttributes` types that the SDK should monitor for real-time updates. **`This method must be invoked within your app's didFinishLaunchingWithOptions method.`** This registration is mandatory for the SDK to successfully track and manage the short tokens required for transactional activity updates.

<CodeGroup>
  ```swift Swift wrap theme={"theme":{"light":"github-light","dark":"github-dark"}}
  Task {
           if #available(iOS 18, *) {
               await MoEngageSDKLiveActivity.monitorLiveActivities(types: [ FoodOrderAttributes.self]) { data in
                       print("Push token generated for live activity",data)
               }
            }
        }

     public struct MoEngageTransactionCampaignData {
          public struct MoEngageTokenData {
                public let transactionId: String
                public let shortToken: String
          }
          
          public let accountMeta: MoEngageAccountMeta
          public let tokenData: MoEngageTokenData
      }

      public class MoEngageAccountMeta {
          /// Account identifier, APP ID on the MoEngage Dashboard.
          public let appID: String
      }
  ```
</CodeGroup>

# Managing the Live Activity Lifecycle

Once your app is configured, you can start, update, and end Transactional Live Activities using a combination of local app code and MoEngage APIs.

## Step 6: Start a Transactional Live Activity

A Transactional Live Activity is typically started locally from the app when an end user initiates a transaction (e.g., placing a food order) or you can initiate it remotely via the Inform API (Server-side).

### Push-to-Start (Remote)

Start a live activity for a user using the Inform API. For more information, refer [here](https://www.moengage.com/docs/api/live-activities/start-broadcast-live-activity).

### Click-to-Start (Local)

Start an activity from within the app, triggered by a user action.

Get Live Activity data from the [createAttributes(withCampaign:completion:)](https://moengage.github.io/ios-api-reference/Enums/MoEngageSDKLiveActivity.html#/s:20MoEngageLiveActivity0ab7SDKLiveD0O16createAttributes12withCampaign4file0J2Id6method4line6column10completionyAC0I0Vy_xG_s12StaticStringVA2PS2uyAM6ResultVy_x_GSgScMYcct0D3Kit0dG0RzlFZ) or [createAttributes(withCampaign:) async](https://moengage.github.io/ios-api-reference/Enums/MoEngageSDKLiveActivity.html#/s:20MoEngageLiveActivity0ab7SDKLiveD0O16createAttributes12withCampaign4file0J2Id6method4line6columnAC0I0V6ResultVy_x_GSgALy_xG_s12StaticStringVA2SS2utYa0D3Kit0dG0RzlFZ) SDK APIs by combining your application's ActivityAttributes data with mandatory MoEngage metadata (retrieved from your server). Use Apple's Activity.request() method with pushType as `.token` to start Live Activity. This links the locally started activity to your campaign.

<CodeGroup>
  ```swift Swift wrap theme={"theme":{"light":"github-light","dark":"github-dark"}}
  MoEngageSDKLiveActivity.createAttributes(
      withCampaign: .init(
          campaignId: campaignId,
          campaignName: "Order Tracking \(orderId)",
          transactionId: transactionId,
          attributeType: "\(FoodOrderAttributes.self)",
          instanceId: instanceId,
          appAttributes: FoodOrderAttributes(orderNumber: "ORD-123", restaurantName: "Pizza Palace"),
          appContent: FoodOrderAttributes.ContentState(status: "Preparing", estimatedMinutes: 30)
      )
  ) { [weak self] result in
      guard let result = result else {
          self?.view.makeToast("No Live Activity creation result")
          return
      }
      
      do {
          let activity = try MoEngageTransactionActivity<FoodOrderAttributes>.request(
              attributes: result.attributes,
              content: .init(
                  state: result.content,
                  staleDate: .distantFuture,
                  relevanceScore: 10
              ),
              pushType: .token,
              style: .standard
          )
          MoEngageSDKLiveActivity.trackStarted(activity: activity)
          self?.view.makeToast("Order Tracking Live Activity started successfully")
      } catch {
          self?.view.makeToast("Activity request error: \"\(error.localizedDescription)\"")
      }
  }
  ```
</CodeGroup>

<Info>
  **Information**

  By using `pushType: .token,`the Live Activity is configured to receive transactional updates specifically targeted to this activity instance via its unique push token.
</Info>

## Step 7: Update a Live Activity

Update the transactional activity status using a push notification targeted at the activity's push token. Updates must be performed exclusively via the Inform API. For more information, refer to the [Inform API](https://www.moengage.com/docs/api/transactional-alerts/send-transactional-alert).

## Step 8: End a Live Activity

Ending an activity must be performed exclusively through the Inform API; otherwise, it will terminate automatically upon reaching the configured `dismissal_date`.

For more information, refer to the [Inform API](https://www.moengage.com/docs/api/transactional-alerts/send-transactional-alert).
