# App Groups for push tracking

You need App Groups for reliable push delivery tracking on iOS. Without this setup, delivery metrics may be lost if iOS terminates the Notification Service Extension before the tracking request completes. With App Groups configured, the SDK automatically recovers any lost metrics on the next app launch.

## Before you begin[](#before-you-begin)

Before you configure App Groups, make sure you’ve completed the following:

*   [Set up push notifications](/integrations/sdk/flutter/push-notifications/push-setup/) in your app, including the Notification Service Extension (NSE)

## 1\. Add the App Group capability in Xcode[](#1-add-the-app-group-capability-in-xcode)

You need to add the App Groups capability to both your main app target and your Notification Service Extension target in Xcode.

 Automatic signing

#### Automatic signing[](#Automatic signing)

If you use automatic signing (the most common setup), this is the only step outside of code. Xcode registers the group and updates provisioning profiles automatically.

1.  In Xcode, select your **main app target** > **Signing & Capabilities** > **\+ Capability** > **App Groups**.
2.  Click **+** and enter your group identifier—for example, `group.com.example.myapp.cio`.
3.  Select your **Notification Service Extension target** > **Signing & Capabilities** > **\+ Capability** > **App Groups**.
4.  Select the **same** App Group you created in step 2.

Both targets must reference the exact same App Group string.

 Manual signing

#### Manual signing[](#Manual signing)

If you use manual signing, you need to register the group in the Apple Developer Portal and regenerate your provisioning profiles.

1.  Sign in to the [Apple Developer Portal](https://developer.apple.com/) and go to **Certificates, Identifiers & Profiles**.
2.  Click **Identifiers** > **+** > **App Groups**.
3.  Enter your identifier. It must start with `group.`—for example, `group.com.example.myapp.cio`.
4.  Under **Identifiers**, select your main app’s App ID, enable **App Groups**, click **Configure**, and select your group.
5.  Repeat step 4 for your Notification Service Extension’s App ID.
6.  Regenerate provisioning profiles for both your main app and Notification Service Extension. Enabling App Groups invalidates your existing provisioning profiles.

 **You must regenerate your provisioning profiles** in the Apple Developer Portal after enabling App Groups. You don’t need to regenerate certificates.

 Already have an App Group?

You can reuse an existing App Group by passing its identifier to `.appGroupId()`. There’s no conflict in having multiple App Groups on a target.

## 2\. Pass the App Group ID in your SDK configuration[](#2-pass-the-app-group-id-in-your-sdk-configuration)

After you add the App Group capability, pass the App Group ID to the SDK in both your host app and your Notification Service Extension. Both are required—App Groups work by sharing storage between the two targets, so the SDK needs the identifier in each place to read and write delivery metrics. The App Group ID must be identical in both places and must match the entitlements you set up in Xcode.

 The `.appGroupId()` method is configured in native Swift code, not in Dart. The Notification Service Extension runs as a separate iOS process outside the Flutter runtime.

### Host app initialization[](#host-app-initialization)

In your `AppDelegate.swift` file, add `.appGroupId()` to the `MessagingPushFCM.initialize` call:

```swift
MessagingPushFCM.initialize(
    withConfig: MessagingPushConfigBuilder()
        .appGroupId("group.com.example.myapp.cio")
        .build()
)
```

### Notification service extension initialization[](#notification-service-extension-initialization)

In your `NotificationService.swift` file, add `.appGroupId()` to the `MessagingPushFCM.initializeForExtension` call:

```swift
MessagingPushFCM.initializeForExtension(
    withConfig: MessagingPushConfigBuilder(cdpApiKey: "YOUR_CDP_API_KEY")
        .appGroupId("group.com.example.myapp.cio")
        .build()
)
```

 App Group ID must match everywhere

The `.appGroupId()` value must be identical in your host app initialization, your NSE initialization, and the App Group entitlements on both targets. A mismatch prevents the SDK from accessing shared storage.

### Fallback behavior[](#fallback-behavior)

If you omit `.appGroupId(...)`, the SDK attempts to infer the identifier using `group.{bundleId}.cio`. This can work as a fallback, but we recommend explicitly passing the value to avoid configuration issues.