Skip to main content

iOS App Store Compliance Checklist

A step-by-step guide to ensure your iOS app with PushEngage push notifications passes Apple's App Store review. Also covers migration from OneSignal and Firebase Cloud Messaging.

Applies to: PushEngage iOS SDK v0.0.6+ | iOS 10.0+

Integration MethodMinimum SwiftMinimum Xcode
CocoaPods5.011+
Swift Package Manager5.915+

How to Use This Checklist

Work through each section in order as you integrate PushEngage and prepare for App Store submission. Each item includes a Verify step so you can confirm completion.

Legend:

  • Required — your app will be rejected without this
  • Recommended — not strictly required but significantly reduces rejection risk
  • Migration — only needed if switching from another push service

Phase 1: Pre-Integration Setup

APNs Certificate (.p12) — Required

Apple Push Notification service requires authentication to send push notifications to your app. The PushEngage dashboard accepts APNs .p12 certificates.

Certificate expiry

.p12 certificates expire annually. Set a calendar reminder 2–4 weeks before expiry to renew — push delivery will silently stop once a certificate expires. Use the "Sandbox & Production" certificate type to cover both development and App Store builds with a single certificate.

  • Create an APNs certificate in the Apple Developer Portal

    • Go to Certificates, Identifiers & Profiles → Certificates
    • Click "+" and select Apple Push Notification service SSL (Sandbox & Production)
    • Complete the CSR flow via Keychain Access:
      1. Open Keychain Access → Certificate Assistant → Request a Certificate From a Certificate Authority
      2. Enter your email, leave CA Email Address empty, select Saved to disk
      3. Upload the generated .certSigningRequest file to the Apple Developer Portal
    • Download the generated .cer file, double-click to install in Keychain Access
    • Open Keychain Access → My Certificates → find "Apple Push Services: com.yourapp.bundleid"
    • Right-click → Export → .p12 format, set an export password
    • Verify: You have a .p12 file and know the export password
  • Upload the .p12 certificate to the PushEngage Dashboard

    • Go to Site Settings → Installation → iOS SDK
    • Fill in the following fields:
      • App Push Id — your app's bundle identifier (e.g., com.yourcompany.yourapp)
      • Certificate (.p12) — upload the .p12 file exported from Keychain Access
      • Private Key Password — the export password set during the .p12 export
    • Click Update
    • Verify: PushEngage Dashboard shows the certificate is configured for iOS push

App ID Configuration — Required

  • Enable Push Notifications for your App ID

  • Create or update your Provisioning Profile

    • After enabling Push Notifications on your App ID, regenerate your provisioning profile
    • Download and install the new profile in Xcode
    • Verify: Xcode → Signing & Capabilities shows no provisioning profile errors

Phase 2: Xcode Project Configuration

Capabilities & Entitlements — Required

  • Add Push Notifications capability

    • Xcode → your target → Signing & Capabilities → + Capability → Push Notifications
    • This adds the aps-environment entitlement to your app
    • Verify: Your .entitlements file contains:
      <key>aps-environment</key>
      <string>development</string>
      (Xcode sets this to production automatically for App Store/TestFlight builds.)
  • Add Background Modes capability with Remote notifications

    • Xcode → your target → Signing & Capabilities → + Capability → Background Modes
    • Check Remote notifications and Background fetch
    • Verify: Your Info.plist contains:
      <key>UIBackgroundModes</key>
      <array>
      <string>fetch</string>
      <string>remote-notification</string>
      </array>
  • Add App Groups capability — Required for SDK to function

    • The PushEngage SDK uses an App Group-backed UserDefaults suite for all internal state (device token, subscriber data, permission status). Without this, the SDK silently loses all stored state between app launches.
    • Xcode → your target → Signing & Capabilities → + Capability → App Groups
    • Create a group identifier, e.g., group.com.yourcompany.yourapp
    • Add the same App Group to your main app target, Notification Service Extension, and any other extensions
    • Add PushEngage_App_Group_Key to each target's Info.plist with the same group identifier
    • Verify: All targets list the same App Group in their .entitlements files:
      <key>com.apple.security.application-groups</key>
      <array>
      <string>group.com.yourcompany.yourapp</string>
      </array>
    • Verify: Each Info.plist contains:
      <key>PushEngage_App_Group_Key</key>
      <string>group.com.yourcompany.yourapp</string>

Notification Service Extension — Required for Rich Notifications & Delivery Tracking

Required for full functionality

The Notification Service Extension is required for rich notifications (images, action buttons), accurate delivery tracking, and badge management. Without it, the SDK can only deliver basic text notifications.

  • Create a Notification Service Extension target

    • Xcode → File → New → Target → Notification Service Extension
    • Name it (e.g., PushEngageNotificationServiceExtension)
    • Set the same deployment target as your main app (iOS 10.0+)
    • Add the PushEngage SDK as a dependency to this target
    • Verify: Your project has a separate Notification Service Extension target
  • Add App Groups to the extension

    • Use the same App Group identifier as your main app
    • Add PushEngage_App_Group_Key to the extension's Info.plist
    • Verify: Extension's .entitlements file contains the matching App Group

Notification Content Extension — Optional

The Notification Content Extension allows custom notification UI. Only add this if you need custom notification layouts.

  • Create a Notification Content Extension target (if needed)

    • Xcode → File → New → Target → Notification Content Extension
    • Configure UNNotificationExtensionCategory in the extension's Info.plist
    • Verify: Extension responds to the correct notification category
  • Add App Groups to the Content Extension

    • Use the same App Group identifier as your main app and Service Extension
    • Add PushEngage_App_Group_Key to the Content Extension's Info.plist
    • Verify: Content Extension's .entitlements file contains the matching App Group

Phase 3: Privacy & Data Compliance

Apple maintains a specific list of third-party SDKs required to include privacy manifests and code signatures. PushEngage is not currently on this list, so Apple will not reject your app solely because the SDK lacks a bundled privacy manifest. However, your app must still declare its own data collection and Required Reason API usage — which includes APIs called by PushEngage.

  • Create your app's privacy manifest (if not already present)

    • Xcode → File → New → File → App Privacy → Privacy Manifest
    • Declare data collection that PushEngage performs (see table below)
    • Declare Required Reason APIs used by PushEngage (see section below)
    • Verify: PrivacyInfo.xcprivacy exists in your app bundle
  • Check for ITMS-91053 warnings during upload

    • These are informational, not blocking, since PushEngage is not on Apple's required list
    • Address them by adding the appropriate declarations to your app's privacy manifest

Data Collected by PushEngage iOS SDK

Data TypePurposeLinked to UserTracking
Device ID (APNs token)Push notification deliveryNoNo
Device modelAnalytics & delivery optimizationNoNo
Device manufacturerAnalytics (hardcoded "Apple")NoNo
Device type (phone/tablet)Analytics & delivery optimizationNoNo
User agent stringAnalytics (derived from device model, e.g. "Apple iPhone14,2")NoNo
OS versionCompatibility & analyticsNoNo
TimezoneScheduled notification deliveryNoNo
Language / localeNotification localizationNoNo
Screen dimensionsNotification display optimizationNoNo
App bundle identifierApp identificationNoNo
Notification permission stateSubscription managementNoNo
APNs environment (dev/prod)Delivery routingNoNo
IP address and location

IP address: The SDK does not collect or send IP addresses from the device. PushEngage's backend servers receive the device's IP address as part of standard HTTP communication. Disclose this in your App Store privacy nutrition labels if your privacy policy covers server-side data.

Location: The SDK does not request GPS/location data or use CoreLocation. It only checks whether your app has declared location usage description keys in Info.plist and reports this as a boolean flag.

IDFA: The SDK does not collect IDFA, does not require App Tracking Transparency, and does not track users across apps.

Required Reason APIs

The PushEngage SDK uses the following API from Apple's "Required Reason" list:

  • Declare NSPrivacyAccessedAPITypes in your app's privacy manifest
    • UserDefaults (NSUserDefaults) — Reason: CA92.1 (App Functionality: app-specific data storage)
    • No other Required Reason APIs are used by the SDK
    • Verify: No ITMS-91053 warnings when uploading to App Store Connect

App Privacy "Nutrition Labels" — Required

When you submit your app to App Store Connect, you must disclose what data your app collects — including data collected by third-party SDKs.

  • Complete the App Privacy section in App Store Connect
    • App Store Connect → Your App → App Privacy
    • Declare the data types listed in the table above
    • For each data type, specify: collected, purpose, linked to user identity, used for tracking
    • Verify: App Store Connect shows your privacy disclosures with no warnings
App Store Connect CategoryDisclose?Details
Do you or your third-party partners collect data from this app?Yes
Identifiers → Device IDYesApp Functionality (push delivery). Not linked to user identity unless your app links it via addProfileId. Not used for tracking.
Usage Data → Product InteractionYesSDK tracks notification views and clicks for delivery analytics. Not linked to user identity. Not used for tracking.
Diagnostics (crash data, performance)NoSDK does not collect crash reports or performance diagnostics.

App Tracking Transparency (ATT) — Not Required for PushEngage

  • Confirm ATT is NOT required for PushEngage
    • PushEngage does not use IDFA or track users across apps
    • You do not need to add NSUserTrackingUsageDescription to your Info.plist for PushEngage
    • Verify: Search your PushEngage integration code for ATTrackingManager — it should not be present
    • Note: If other SDKs in your app use IDFA, you still need ATT for those

Phase 4: App Store Review Guidelines Compliance

Apple's review guidelines have specific rules about push notifications. Violating these is one of the most common causes of rejection.

Content & Behavior Rules — Required

  • Do NOT require push notifications to use the app (Guidelines 4.5.4, 5.1.2)

    • Apps cannot require users to enable push notifications to access features or receive compensation
    • Do not gate content, features, or rewards behind push notification opt-in
    • Verify: Test your app with notifications denied — all features should work
  • Keep notification content relevant to the app (Guideline 2.5.16)

    • Notifications must relate to your app's core content and functionality
    • Do not send notifications unrelated to what the user signed up for
    • Verify: Review your notification campaigns in PushEngage Dashboard — all should relate to app content
  • No advertising in push notifications without explicit opt-in (Guideline 4.5.4)

    • Push notifications must not be used for promotions or direct marketing unless users have explicitly opted in via consent language in your app
    • You must provide a method to opt out of such messages
    • Promotional content for your own app features is generally acceptable if the user opted in
    • Verify: Review notification templates — none should contain unsolicited promotional content
  • No spam or unsolicited notifications (Guideline 4.5.4)

    • Send notifications at reasonable frequency; content should provide value
    • Do not use push as a re-engagement mechanism for inactive users without consent
    • Verify: Check notification frequency in PushEngage analytics — avoid more than 2–3 per day unless user-triggered
  • Provide notification preferences — Recommended

    • Include an in-app setting for users to manage notification types or frequency
    • Reviewers look favorably on this even though it's not strictly required
    • Verify: Your app has a Settings screen with notification preferences
  • Request notification permission at an appropriate time

    • Do NOT request permission immediately on first launch
    • Show a pre-permission screen explaining the value of notifications before the system prompt
    • Request permission after the user has experienced your app's core value
    • Verify: Test a fresh install — the system permission prompt should not appear on the first screen
  • Handle permission denial gracefully

    • If the user denies, do not repeatedly prompt
    • Provide a path to enable notifications later via Settings
    • Verify: Deny permissions and use the app — no repeated prompts or degraded experience

Phase 5: Migration Compliance

Skip if new integration

Skip this section if this is a fresh integration without a previous push notification service.

Migrating from OneSignal — Migration

Privacy manifest impact

OneSignal is on Apple's required third-party SDK list. Removing it removes its privacy manifest and code signature requirements from your app.

  • Remove OneSignal SDK completely

    • Remove from Podfile / Package.swift
    • Delete all OneSignal import statements and API calls
    • Remove OneSignal's Notification Service Extension (if separate from yours)
    • Verify:
      grep -r "OneSignal" --include="*.swift" --include="*.m" --include="*.h" .
      # Should return no results
  • Remove OneSignal's privacy manifest entries

    • Remove any OneSignal-specific entries from your privacy manifest
    • Add PushEngage's data collection declarations (see Phase 3)
    • Verify: Your PrivacyInfo.xcprivacy no longer references OneSignal data types
  • Update App Privacy nutrition labels

    • OneSignal and PushEngage collect similar but not identical data
    • Review your App Store Connect privacy disclosures and update accordingly
    • Verify: App Store Connect privacy section reflects PushEngage's data collection
  • Upload your APNs credential to PushEngage

    • Your existing APNs .p12 certificate works with PushEngage — no change needed to the certificate itself
    • Go to Site Settings → Installation → iOS SDK and upload the same .p12 certificate you used with OneSignal
    • Verify: Test push notification delivered successfully via PushEngage
  • Map subscriber data

    • OneSignal Player IDs do not transfer to PushEngage
    • Device tokens are re-registered automatically when the PushEngage SDK initializes
    • If you stored OneSignal Player IDs in your backend, plan for the subscriber migration
    • Verify: New subscribers appear in PushEngage Dashboard after SDK switch

Migrating from Firebase Cloud Messaging (FCM) — Migration

Other Firebase SDKs

FirebaseMessaging is on Apple's required third-party SDK list. If you remove it but keep other Firebase SDKs (e.g., FirebaseCore, FirebaseCrashlytics), those still require their own privacy manifests.

  • Keep Firebase dependencies if using other Firebase services

    • PushEngage uses APNs directly, not FCM
    • If you use Firebase for Analytics, Crashlytics, etc., keep those dependencies
    • Remove only FCM-specific notification handling code
    • Verify: Other Firebase services still work after removing FCM notification code
  • Remove FCM notification handling code

    • Remove FIRMessaging delegate methods and FIRMessagingDelegate conformance
    • Remove the messaging:didReceiveRegistrationToken: handler
    • Keep Firebase initialization if using other Firebase services
    • Verify:
      grep -r "FIRMessaging\|FirebaseMessaging" --include="*.swift" --include="*.m" .
      # Should return no notification-specific results
  • Update privacy manifest for FCM removal

    • If FCM had entries in your privacy manifest, remove them
    • Firebase Analytics (if kept) has its own privacy manifest — ensure it's still included
    • Verify: Build succeeds with no ITMS-91053 warnings
  • Upload your APNs credential to PushEngage

    • FCM wraps APNs internally; PushEngage connects to APNs directly
    • Go to Site Settings → Installation → iOS SDK and upload a .p12 certificate (see Phase 1 if you need to create one)
    • Verify: Test push delivered via PushEngage (not through FCM relay)
  • Handle dual-SDK transition period (if migrating gradually)

    • If running both services temporarily, ensure only one service handles each notification
    • Use notification categories or payload keys to distinguish
    • Verify: No duplicate notifications received during transition

Phase 6: Pre-Submission Final Checklist

Run through this section before every App Store submission.

Entitlements & Capabilities

  • Push Notifications capability enabled in Xcode
  • Background Modes → Remote notifications enabled
  • App Groups configured with PushEngage_App_Group_Key in Info.plist for all targets
  • aps-environment set to production for App Store builds (Xcode sets this automatically)
  • Provisioning profile is current and includes Push Notifications

Verify the aps-environment entitlement in your built app:

codesign -d --entitlements :- /path/to/YourApp.app 2>&1 | grep aps-environment
# Should show: <string>production</string>

Privacy

  • PrivacyInfo.xcprivacy exists in your app bundle with PushEngage data declarations
  • UserDefaults declared as Required Reason API with reason CA92.1
  • App Privacy nutrition labels completed in App Store Connect
  • No ITMS-91053 or ITMS-91061 warnings in Xcode or Transporter

Notifications

  • Test push notification received on a physical device (Simulator cannot receive push notifications)
  • Rich notifications display correctly (images, action buttons) — requires Notification Service Extension
  • Deep links from notifications navigate to the correct screens
  • Notification permission denial does not break any app functionality
  • No notification-gated content or forced opt-ins
  • Notification content is relevant to app functionality

Code Cleanup

  • No previous SDK references (OneSignal / FCM) remain in code
  • No debug APNs configuration in production build
  • PushEngage logging disabled for production: PushEngage.enableLogging = false
  • No hardcoded test device tokens in code

Build & Archive

  • Archive build succeeds with no signing errors
  • Transporter / Xcode upload shows no new warnings
  • TestFlight build receives push notifications correctly

Common App Store Rejection Reasons

Rejection ReasonGuidelineHow to Avoid
App requires push notifications to function4.5.4, 5.1.2Ensure all features work without notifications enabled
Notifications used for unsolicited marketing4.5.4Only send promotions if user explicitly opted in; provide opt-out
Notifications unrelated to app content2.5.16Keep notification content related to your app's functionality
Excessive or irrelevant notifications4.5.4Limit frequency; keep content relevant to app
Missing privacy disclosures for push data5.1.1Complete App Privacy section and privacy manifest
Invalid provisioning profileN/ARegenerate profile after enabling Push Notifications capability
Missing push entitlementN/AAdd Push Notifications capability in Xcode
Privacy manifest warningsN/AInclude PrivacyInfo.xcprivacy with required declarations

iOS Version Considerations

RequirementiOS 10–11iOS 12+iOS 17+iOS 18+
Push Notifications capabilityRequiredRequiredRequiredRequired
Background ModesRequiredRequiredRequiredRequired
App-level Privacy ManifestRequired for all App Store submissions since May 2024
Provisional NotificationsN/AAvailableAvailableAvailable
Notification CategoriesAvailableAvailableAvailableAvailable
Priority NotificationsN/AN/AN/AAvailable
Provisional notifications

iOS 12 introduced provisional (quiet) notifications that require no user permission prompt. PushEngage SDK v0.0.6 does not request provisional authorization — it requests .alert, .badge, and .sound only. If you need provisional delivery, you would need to request it separately via UNUserNotificationCenter before calling PushEngage initialization.

Privacy Manifest

The privacy manifest is an App Store Connect submission requirement, not an iOS runtime feature. You need it in your app bundle regardless of which iOS version you target.


Useful Commands & Verification Tools

Check entitlements in your built app:

codesign -d --entitlements :- /path/to/YourApp.app

Search for old SDK references:

# Search for OneSignal
grep -r "OneSignal" --include="*.swift" --include="*.m" --include="*.h" \
--include="*.plist" --include="*.pbxproj" .

# Search for Firebase Messaging
grep -r "FIRMessaging\|FirebaseMessaging" --include="*.swift" --include="*.m" \
--include="*.plist" --include="*.pbxproj" .

Verify privacy manifest in built app:

find /path/to/YourApp.app -name "PrivacyInfo.xcprivacy"

Check .p12 certificate expiry date:

# View certificate details including expiry date
openssl pkcs12 -in YourCert.p12 -nokeys | openssl x509 -noout -dates
# Look for "notAfter" — that is your expiry date

Test APNs connectivity with your .p12 certificate:

# Step 1: Convert .p12 to .pem (enter your export password when prompted)
openssl pkcs12 -in YourCert.p12 -out apns-cert.pem -nodes
# If you see an "unsupported" or "Mac verify error" with OpenSSL 3 (e.g. Homebrew),
# retry with the legacy provider:
# openssl pkcs12 -legacy -in YourCert.p12 -out apns-cert.pem -nodes

# Step 2: Get your device token from Xcode console when your app registers

# Step 3: Send a test push
curl -v --cert apns-cert.pem \
--header "apns-topic: com.yourapp.bundleid" \
--header "apns-push-type: alert" \
--data '{"aps":{"alert":"Test from curl","sound":"default"}}' \
--http2 https://api.push.apple.com/3/device/YOUR_DEVICE_TOKEN

# For sandbox/development testing use:
# https://api.sandbox.push.apple.com/3/device/YOUR_DEVICE_TOKEN

Next Steps