Skip to main content

Ios Uninstall Tracking (APN)

Overview

Track app uninstalls using Apple Push Notification Service (APNs) to measure user retention and optimize your campaigns.

info

iOS uninstalls take 9+ days to appear in reports due to Apple Push Notification service.


Prerequisites

  • iOS 10.0 or higher
  • Xcode 12.0 or later
  • Apple Developer Account
  • Apptrove Cordova SDK version 1.6.78+ installed

Step 1: Request Certificate in Keychain Access

1.1. Open Keychain Access on your Mac.

1.2. Go to Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority.

Request Certificate

1.3. Fill in the form:

  • User Email Address: Your email
  • Common Name: Your name
  • Request is: Select Saved to disk
  • Click Continue

1.4. Save the file to your Desktop.

Save to Disk


Step 2: Go to Apple Developer Portal - Identifiers

2.1. Open Apple Developer Portal.

2.2. Go to Certificates, Identifiers & Profiles.

2.3. Click Identifiers.

2.4. Select your App ID (your app's bundle ID/package name).

Identifiers


Step 3: Configure Push Notifications

3.1. After clicking your App ID, you'll see the App ID Configuration page.

3.2. Scroll to Capabilities section.

3.3. Check Push Notifications.

3.4. Click Configure.

Push Notifications Configuration


Step 4: Upload Certificate and Download .cer

4.1. In the Push Notifications configuration screen, choose:

  • Production SSL Certificate (for App Store/Production)
  • Click Create Certificate

4.2. Click Choose File and upload the .certSigningRequest file from Step 1.

4.3. Click Continue.

4.4. Click Download to save the .cer file.

Download .cer Certificate


Step 5: Go to Keychain and Export as .p12

5.1. Double-click the downloaded .cer file to open it in Keychain Access.

5.2. In Keychain Access, click My Certificates in the left sidebar.

5.3. Find your Push Notification certificate (e.g., "Apple Push Services: com.yourapp.package").

5.4. Right-click on the certificate → Select Export.

5.5. Save as:

  • File Format: Personal Information Exchange (.p12)
  • Enter a password (you will need this later)
  • Click Save

Export .p12 Certificate


Step 6: Upload .p12 to Apptrove Panel

6.1. Log in to your Apptrove Panel.

6.2. Go to Settings > Uninstall Tracking.

6.3. Select your iOS app.

6.4. Click Upload and select the .p12 file.

6.5. Enter the password you created in Step 5.

6.6. Click Save.


Step 7: Configure in Xcode

7.1. Open your project in Xcode:

npx cap open ios

7.2. Select your app TargetSigning & Capabilities tab.

7.3. Click + Capability → Add Push Notifications.

7.4. Click + Capability again → Add Background Modes.

7.5. Check Remote notifications.

Background Modes


Next Steps: APN Code Implementation

Now we'll continue with the APN code implementation to send the token to Trackier SDK.

The following steps will cover:

  1. Install Dependencies - Add @capacitor/push-notifications plugin
  2. Info.plist - Add user permission description
  3. App.entitlements - Configure aps-environment for push notifications
  4. AppDelegate.swift - Set up push notification handlers to forward tokens to Capacitor
  5. Cordova Service - Create APN service to receive token and send to Trackier SDK using sendAPNToken()

Let's proceed with the code implementation:


Step 9: Install Dependencies

Add Capacitor Push Notifications plugin to your project:

npm install @capacitor/push-notifications
npx cap sync

Step 10: Add User Permission in Info.plist

10.1. Open your project in Xcode.

10.2. Open the Info.plist file.

10.3. Add the following key and description:

Key: NSUserNotificationsUsageDescription

Value: We need permission to send you notifications and track uninstalls.

You can also add it in the Source Code view:

<key>NSUserNotificationsUsageDescription</key>
<string>We need permission to send you notifications and track uninstalls.</string>
note

This permission message will be shown to users when your app requests notification access.

Background Modes

When you enable Background Modes capability with Remote notifications in Step 7, Xcode automatically adds UIBackgroundModes with remote-notification to your Info.plist. You don't need to add this manually.


Step 11: Configure App.entitlements

11.1. Open your project in Xcode.

11.2. Ensure the App.entitlements file exists (it should be created automatically when you add capabilities).

11.3. Add or verify the aps-environment key:

ios/App/App/App.entitlements
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>
Production vs Development

Change aps-environment to production when building for App Store release. Use development for testing and development builds.


Step 12: Configure AppDelegate.swift

Update your AppDelegate.swift to handle push notification registration:

ios/App/App/AppDelegate.swift
import UIKit
import Capacitor

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}

// MARK: - Push Notifications

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// Forward the token to Capacitor's notification plugin
NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
// Forward the error to Capacitor's notification plugin
NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
}
}

Step 13: Send Token to Trackier SDK

Create an Angular service to handle APN token management:

src/app/services/apn.service.ts
import { Injectable } from '@angular/core';
import { Platform } from '@ionic/angular';
import { PushNotifications, Token } from '@capacitor/push-notifications';
import { TrackierCordovaPlugin } from 'com.trackier.cordova_sdk/ionic-native/trackier/ngx';

@Injectable({
providedIn: 'root'
})
export class ApnService {
constructor(
private platform: Platform,
private trackierCordovaPlugin: TrackierCordovaPlugin
) {}

async initializeAPN(): Promise<void> {
if (!this.platform.is('ios')) {
return;
}

const permStatus = await PushNotifications.requestPermissions();

if (permStatus.receive === 'granted') {
await PushNotifications.register();

PushNotifications.addListener('registration', (token: Token) => {
console.log('APN Token received:', token.value);
// Send to Trackier SDK
this.trackierCordovaPlugin.sendAPNToken(token.value);
});

PushNotifications.addListener('registrationError', (error: any) => {
console.error('Error on APN registration:', error);
});
}
}
}

Initialize in your app.component.ts after SDK initialization:

src/app/app.component.ts
import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';
import { TrackierCordovaPlugin, TrackierConfig } from 'com.trackier.cordova_sdk/ionic-native/trackier/ngx';
import { ApnService } from './services/apn.service';

@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
})
export class AppComponent {
constructor(
private platform: Platform,
private trackierCordovaPlugin: TrackierCordovaPlugin,
private apnService: ApnService
) {
this.initializeApp();
}

async initializeApp() {
await this.platform.ready();

const trackierConfig: TrackierConfig = {
appToken: 'YOUR_SDK_KEY',
environment: 'production'
};

await this.trackierCordovaPlugin.initializeSDK(trackierConfig);

// Initialize APN after SDK initialization (iOS only)
if (this.platform.is('ios')) {
await this.apnService.initializeAPN();
}
}
}

Step 14: Check Logs

Run your app on a physical device (Simulator doesn't support APNs).

Check Xcode console logs. You should see:

APN Token: b0adf7c9730763f88e1a048e28c68a9f806ed032fb522debff5bfba010a9b052
Apn token Api response saved successfully

Verify Logs

| Success: "Apn token Api response saved successfully"

| Error: If you see an error message, check the troubleshooting section below.


Troubleshooting

Issue: Token Not Generated

Check:

  • Push Notifications capability is enabled in Xcode
  • Testing on physical device (not Simulator)
  • User granted notification permission

Issue: "API Response Failed" Error

Check:

  • .p12 certificate uploaded to Apptrove panel
  • Password is correct
  • Using Production certificate for App Store builds
  • SDK is initialized before calling sendAPNToken

Issue: User Denied Notification Permission

Solution: User must enable in Settings > [Your App] > Notifications

Issue: Uninstalls Not Appearing in Dashboard

Remember: Takes 9+ days to appear for production builds.


Complete Flow Summary

  1. Keychain Access → Request Certificate → Save .certSigningRequest file
  2. Apple Developer Portal → Identifiers → Select your App ID
  3. Configure Push Notifications → Enable and click Configure
  4. Upload Certificate Request → Download .cer file
  5. Keychain Access → Export .cer as .p12 with password
  6. Apptrove Panel → Upload .p12 file + password
  7. Xcode → Enable Push Notifications + Background Modes
  8. Install Dependencies → Install @capacitor/push-notifications plugin (Step 9)
  9. Info.plist → Add user permission description (Step 10)
  10. App.entitlements → Add aps-environment key (Step 11)
  11. AppDelegate.swift → Configure push notification handlers (Step 12)
  12. Cordova App → Create APN service and call trackierCordovaPlugin.sendAPNToken(token) (Step 13)
  13. Check Logs → Verify "Apn token Api response saved successfully" (Step 14)

SDK Method

sendAPNToken(token)

Send the APN token to Apptrove for uninstall tracking.

Usage:

this.trackierCordovaPlugin.sendAPNToken(apnToken);

When to call: After SDK initialization, when APN token is received from Capacitor Push Notifications plugin.


For support, contact support@trackier.com.