# Set Up Client Integration

{% hint style="info" %}
ContextPush currently is only supported for iOS. If you’re interested in using ContextPush in other platforms or languages, contact us at <support@contextsdk.com>.
{% endhint %}

{% stepper %}
{% step %}

#### Create a License Key & Install the SDK

Check out [getting-started](https://docs.contextsdk.com/basics/getting-started "mention") for details on how to create your license key and install the SDK.
{% endstep %}

{% step %}

#### Import ContextSDK

{% code title="AppDelegate.swift" %}

```swift
import ContextSDK
```

{% endcode %}
{% endstep %}

{% step %}

#### Ensure Necessary Entitlement

In your Xcode project, go to `Signing & Capabilities` and enable the `Background fetch`, `Background processing` and `Remote notifications` capabilities in the `Background Modes` section.
{% endstep %}

{% step %}

#### Ensure Tasks are Registered

In your Xcode project, go to `Info` and add the `com.contextsdk.push.refresh-task` and `com.contextsdk.push.processing-task` to the list of `Permitted background task scheduler identifiers`.
{% endstep %}

{% step %}

#### Enable ContextPush

In your `AppDelegate` or similar in the `applicationDidFinishLaunchingWithOptions` or equivalent call `ContextPush.applicationDidFinishLaunchingWithOptions()`. If everything worked you should see "\[ContextSDK] Successfully scheduled next check for ContextPush."

{% code title="AppDelegate.swift" %}

```swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Your existing app startup code

    ContextPush.applicationDidFinishLaunchingWithOptions()
}
```

{% endcode %}
{% endstep %}

{% step %}

#### Understanding Background Wake-Up Behavior

{% hint style="warning" %}
**Important:** ContextPush uses background processing and silent push notifications to wake your app periodically in the background. This allows the SDK to assess the user's real-world context for optimal notification timing.
{% endhint %}

When ContextPush wakes your app in the background, iOS may call `application(_:didFinishLaunchingWithOptions:)` while your app is not in the foreground. This can have side effects if your app logic assumes this method only runs when the app is being launched by the user.

**Recommended Approach: Use Lifecycle Notifications**

The recommended way to handle foreground-specific logic is to use UIScene lifecycle methods or lifecycle notifications instead of checking the application state manually:

{% tabs %}
{% tab title="UISceneDelegate (Recommended)" %}
For apps using UIScene, implement `sceneDidBecomeActive(_:)` in your `UISceneDelegate`:

{% code title="SceneDelegate.swift" %}

```swift
func sceneDidBecomeActive(_ scene: UIScene) {
    // This is called when your app enters the foreground
    // Place foreground-specific initialization code here
}
```

{% endcode %}
{% endtab %}

{% tab title="UIApplication Notifications" %}
For apps not using UIScene, observe `UIApplication.didBecomeActiveNotification`:

{% code title="AppDelegate.swift" %}

```swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Your existing app startup code

    ContextPush.applicationDidFinishLaunchingWithOptions()

    // Observe when the app becomes active
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(applicationDidBecomeActive),
        name: UIApplication.didBecomeActiveNotification,
        object: nil
    )

    return true
}

@objc private func applicationDidBecomeActive() {
    // This is called when your app enters the foreground
    // Place foreground-specific initialization code here
}
```

{% endcode %}
{% endtab %}

{% tab title="Manual State Check (Alternative)" %}
If you need to check the application state manually in `application(_:didFinishLaunchingWithOptions:)`:

{% code title="AppDelegate.swift" %}

```swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Your existing app startup code

    ContextPush.applicationDidFinishLaunchingWithOptions()

    // Only run foreground-specific code when app is in foreground
    if application.applicationState != .background {
        // Place foreground-specific initialization code here
    }

    return true
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

**Best Practices**

* Move foreground-specific initialization logic (e.g., presenting onboarding screens, tracking app launches, or showing promotional content) to lifecycle methods that are specifically called when the app enters the foreground.
* Keep your `application(_:didFinishLaunchingWithOptions:)` implementation lightweight and suitable for both foreground and background launches.
* Test your app's behavior when woken up in the background to ensure no unexpected UI presentations or crashes occur.
  {% endstep %}

{% step %}

#### Provide User ID and Push Token

You need to register the user's device with a unique user ID and the device's push token. The user-id may be whatever you use to identify each user in your existing push notification system, e.g. an email address or a user ID from your database.

{% tabs %}
{% tab title="Set Device Token and User ID Together" %}
{% code title="AppDelegate.swift" %}

```swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Your existing code for handling device token registration

    // Set the device token and user ID with ContextSDK to enable push notifications
    ContextPush.setDeviceToken(deviceToken).setUserId(userId)
}
```

{% endcode %}
{% endtab %}

{% tab title="Set Device Token Separately" %}
{% code title="AppDelegate.swift" %}

```swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  // Your existing code for handling device token registration

  // Set the device token with ContextSDK to register the device for push notifications
  ContextPush.setDeviceToken(deviceToken)
}
```

{% endcode %}
{% endtab %}

{% tab title="Set User ID Separately" %}

```swift
// Set the user ID once it is available to associate notifications with the correct user
ContextPush.setUserId(userId)
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Handle Background Notifications

Ensure that your app can handle push notifications received while in the background by implementing the following method:

{% code title="AppDelegate.swift" %}

```swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any],fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // ContextSDK will process the notification if it is a valid ContextPush notification
    // The completion handler will be automatically called if processed
    if ContextPush.applicationDidReceiveRemoteNotification(userInfo, fetchCompletionHandler: completionHandler) {
        return
    }
    // Handle other types of background notifications with your existing code, if needed
}
```

{% endcode %}
{% endstep %}

{% step %}

#### Handle Notification Opens

Track when users open notifications to gather engagement metrics and improve user experience:

{% code title="AppDelegate.swift" %}

```swift
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    // Process the notification with ContextSDK to track open rates and user interactions
    ContextPush.userNotificationCenterDidReceiveResponse(response)

    // Your existing code
    // Ensure completion handler is called to finalize notification handling
    completionHandler()
}
```

{% endcode %}
{% endstep %}

{% step %}

#### (Optional) Customize Notification Content

If you need to customize notifications beyond what ContextPush supports by default, you can provide a callback to modify the notification content before it is displayed. This is useful for:

* Adding custom attachments or media
* Modifying text based on app state or localization
* Adding custom sounds
* Setting additional notification properties

{% code title="AppDelegate.swift" %}

```swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Your existing app startup code

    ContextPush.applicationDidFinishLaunchingWithOptions()

    // Optional: Customize notification content before display
    ContextPush.setNotificationContentCustomizer { content, userInfo in
        // Example: Add a custom subtitle based on app state
        content.subtitle = "Special offer just for you!"

        // Example: Add a custom sound
        content.sound = UNNotificationSound(named: UNNotificationSoundName("custom.caf"))

        // Return the modified content (or a new UNNotificationContent)
        return content
    }

    return true
}
```

{% endcode %}

The callback receives:

* `content`: The `UNMutableNotificationContent` built by ContextSDK from the push payload
* `userInfo`: The notification's user info dictionary, including your custom data

To disable customization, set the customizer to `nil`:

```swift
ContextPush.setNotificationContentCustomizer(nil)
```

{% endstep %}

{% step %}

#### Test Your Setup

1. Visit your [dashboard](https://dashboard.contextsdk.com)
2. Select <kbd>**Integrate Push**</kbd> in the menu
   * If this option is still not available to you, request access in <kbd>**Products Info**</kbd> → <kbd>**ContextPush**</kbd>
3. Upload your push certificate and fill in the necessary information
   * This will grant you access to your API token, which will be used later on.
   * You can either create a new push certificate for ContextPush, or use your existing one.
4. Test your push setup by using the <kbd>**Test Push Integration**</kbd> feature
   {% endstep %}

{% step %}

#### Integrate With Your Push Notification Provider

You're now done integrating with the iOS app. Next, integrate with your existing push provider:

<table data-view="cards"><thead><tr><th data-type="content-ref"></th></tr></thead><tbody><tr><td><a href="push-notification-providers/onesignal">onesignal</a></td></tr><tr><td><a href="push-notification-providers/customer.io">customer.io</a></td></tr><tr><td><a href="push-notification-providers/simple-web-request">simple-web-request</a></td></tr></tbody></table>

If you can't find your provider in this list, don't worry: you can integrate ContextPush with any provider, as long as it supports webhooks. Reach out to us to let us know which provider you use and we'll guide you through the integration steps.
{% endstep %}
{% endstepper %}

***

## Required: Notification Service Extension

ContextPush requires a Notification Service Extension to enable reporting when your app is not running.

{% content-ref url="notification-service-extension" %}
[notification-service-extension](https://docs.contextsdk.com/context-push/notification-service-extension)
{% endcontent-ref %}
