Skip to content
Last updated

iOS Developer Guide

Beta Feature

Mobile Push is currently in beta. Features, APIs, and implementation details may change before general availability.

Overview

This guide provides implementation requirements for integrating Engage Studio Mobile Push notifications in your iOS app using the Treasure Data iOS SDK. Your development team must implement the following functionality:

  1. APNs/FCM Integration: Receive push notifications via Apple Push Notification Service and Firebase Cloud Messaging
  2. Token Management: Register and update device tokens with Treasure Data
  3. Rich Notifications: Display notifications with images using Notification Service Extension
  4. Event Tracking: Track user interactions (delivery, open, dismiss, links) using Treasure Data SDK
  5. Automated Data Upload: Treasure Data SDK automatically handles event upload to Treasure Data
Sample Implementation Available

A complete, production-ready sample application is available on GitHub:

Treasure Data Mobile Push - iOS Sample

The sample includes:

  • Complete AppDelegate implementation with FCM and Treasure Data SDK integration
  • Notification Service Extension for rich media
  • Event tracking with Treasure Data SDK
  • Deep link and web link handling

Clone the repository and use it as a reference for your implementation.

Requirements

ComponentRequirement
Minimum iOS VersioniOS 15.0 or later
LanguageSwift (recommended) or Objective-C
Required Frameworks
  • Firebase Messaging SDK 12.7.0+
  • Treasure Data iOS SDK 1.2.1+
  • UserNotifications framework
  • SafariServices (for web link handling)
Xcode VersionXcode 14.0 or later
Tracked Eventsdelivery, open, dismiss, deeplink_open, link_open, token_register

Architecture Overview

Your iOS app implementation consists of the following components:

1. AppDelegate Configuration

Purpose: Initialize Firebase, Treasure Data SDK, and configure notification delegates

Key Responsibilities:

  • Initialize Firebase SDK
  • Initialize Treasure Data SDK with endpoint and database configuration
  • Set notification center delegates
  • Request notification permissions from user
  • Register for remote notifications
  • Handle notification events in foreground and background

Reference: See AppDelegate.swift in the sample repository

2. Notification Service Extension

Purpose: Download and attach images to notifications

Key Responsibilities:

  • Receive notification before display
  • Extract image_url from payload
  • Download image from remote URL
  • Create UNNotificationAttachment
  • Add attachment to notification content

Reference: See NotificationService.swift in the sample repository

3. Tracking Service

Purpose: Manage event tracking with Treasure Data SDK

Key Responsibilities:

  • Track all push notification events using Treasure Data SDK
  • Handle delivery, open, dismiss, link_open, and deeplink_open events
  • Associate events with FCM token and user ID
  • Manage event data formatting

Reference: See TrackingService.swift in the sample repository

Purpose: Handle deep links from notifications

Key Responsibilities:

  • Receive deep link URLs via SceneDelegate or AppDelegate
  • Parse URL scheme and path
  • Navigate to appropriate screen based on deep link
  • Open web URLs in Safari
  • Track deep link events

Reference: See SceneDelegate.swift in the sample repository

Project Setup

Step 1: Generate Xcode Project with XcodeGen

The sample app uses XcodeGen to generate the Xcode project. Install XcodeGen:

brew install xcodegen

Generate the Xcode project:

cd ios
xcodegen generate

Step 2: Add Firebase and Treasure Data SDK

The project uses Swift Package Manager for dependency management. Dependencies are defined in project.yml:

Firebase iOS SDK (12.7.0+):

  • FirebaseMessaging
  • FirebaseAnalytics

Treasure Data iOS SDK (1.2.1+):

  • Complete SDK for event tracking and data upload

Dependencies are automatically resolved when you open the generated Xcode project.

Step 3: Configure Firebase

  1. Download GoogleService-Info.plist from Firebase Console

  2. Copy the file to your project:

    cp GoogleService-Info.plist ios/TDPushSample/GoogleService-Info.plist
  3. Ensure the file is added to your main app target in Xcode

Step 4: Configure Treasure Data in Info.plist

Add your Treasure Data configuration to Info.plist:

<key>TDWriteKey</key>
<string>your_write_api_key_here</string>
<key>TDDatabase</key>
<string>mobile</string>
<key>TDTable</key>
<string>push_events</string>
<key>TDEndpoint</key>
<string>https://in.treasuredata.com</string>

Important: Do not commit your actual API key to version control. Use placeholder values and document the required configuration.

Step 5: Configure Capabilities in Xcode

  1. Select your project in Project Navigator
  2. Select your app target
  3. Go to Signing & Capabilities tab
  4. Click + Capability and add:
    • Push Notifications
    • Background Modes → Check Remote notifications

Step 6: Create Notification Service Extension (for Rich Media)

To support images in notifications, you need a Notification Service Extension:

  1. In Xcode, go to File > New > Target
  2. Select Notification Service Extension
  3. Enter extension name (e.g., NotificationService)
  4. Click Finish

Add URL scheme support to Info.plist:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>myapp</string>
        </array>
        <key>CFBundleURLName</key>
        <string>com.example.myapp</string>
    </dict>
</array>

Data Payload Schema

Your app will receive the following JSON structure in the notification userInfo:

{
  "td_campaign_id": "cmp_20251214_promo",
  "title": "Special Offer!",
  "body": "Get 20% off your next purchase",
  "image_url": "https://cdn.example.com/banner.png",
  "link": "https://example.com/promo"
}
FieldTypeRequiredDescription
td_campaign_idStringYesUnique campaign identifier from Engage Studio
titleStringYesNotification title
bodyStringYesNotification body text
image_urlStringNoURL for rich notification image
linkStringNoWeb URL to open in Safari

Event Tracking

Your app must track the following events and send them to Treasure Data:

Event TypeWhen to TrackRequired Fields
deliveryWhen notification is received and displayedcampaign_id, platform, time
openWhen user taps the notificationcampaign_id, platform, time, user_id
dismissWhen user dismisses the notificationcampaign_id, platform, time, user_id
link_openWhen user taps a web linkcampaign_id, platform, time, user_id, value (URL)
deeplink_openWhen user taps a deep linkcampaign_id, platform, time, user_id, value (URI)
token_registerWhen FCM token is obtained or refreshedfcm_token, platform, time, user_id (if logged in)

All events are automatically sent by the Treasure Data SDK to the configured Treasure Data endpoint. The SDK handles batching, queuing, and retry logic automatically.

See the Push Events Table documentation for complete schema details.

Testing

Test on Simulator (iOS 13+)

iOS Simulator supports push notifications from iOS 13 and Xcode 11.4+:

  1. Create a test payload file test-notification.apns:
{
  "Simulator Target Bundle": "com.example.myapp",
  "aps": {
    "alert": {
      "title": "Test Notification",
      "body": "This is a test message"
    },
    "sound": "default",
    "badge": 1
  },
  "campaign_id": "test_campaign",
  "deeplink": "myapp://test"
}
  1. Send to simulator:
xcrun simctl push booted com.example.myapp test-notification.apns

Test on Physical Device

  1. Get your FCM token from app logs
  2. Open Firebase Console > Cloud Messaging
  3. Click Send your first message
  4. Enter title and body
  5. Click Send test message
  6. Enter your FCM token
  7. Verify notification appears on device

Verify Event Tracking

Query Treasure Data to confirm events are being logged:

SELECT
  time,
  type,
  campaign_id,
  platform
FROM mobile.push_events
WHERE platform = 'ios'
ORDER BY time DESC
LIMIT 100

User ID Association

To link push notification events with specific users, pass the user_id when registering the FCM token.

Implementation Notes:

  • Logged-in users: Include user_id (e.g., customer ID, email hash) in token registration events
  • Not logged-in users: Pass nil for user_id — Treasure Data will associate the token later when the user logs in
  • Name resolution: Treasure Data links events by matching fcm_token values over time

Troubleshooting

Notifications not received

  1. Check APNs certificate: Verify APNs authentication key is uploaded to Firebase Console
  2. Check Bundle ID: Ensure Bundle ID in Xcode matches Firebase registration (case-sensitive)
  3. Check notification permissions: Verify app has notification permission in Settings > Notifications
  4. Check device registration: Confirm didRegisterForRemoteNotificationsWithDeviceToken is called
  5. Test with Firebase Console: Send test notification directly from Firebase

Rich images not displaying

  1. Verify Notification Service Extension: Check extension is properly configured and added to app
  2. Check image URL: Ensure URL is HTTPS and image is accessible
  3. Check extension logs: Use Console.app to view extension logs
  4. Check file size: Large images may timeout (limit ~10MB)

Events not appearing in Treasure Data

  1. Check write key: Verify TDWriteKey in Info.plist is correct and active
  2. Check endpoint: Ensure TDEndpoint matches your region (US, Tokyo, EU)
  3. Check table name: Confirm TDDatabase and TDTable exist in Treasure Data
  4. Check SDK initialization: Verify Treasure Data SDK is initialized in AppDelegate
  5. Enable logging: Add TreasureData.enableLogging() to see SDK activity
  6. Force upload: Try calling TreasureData.sharedInstance().uploadEvents() manually
  1. Verify URL scheme: Check Info.plist has correct CFBundleURLTypes configuration
  2. Test deep link: Use Safari to test: Enter myapp://test in address bar
  3. Check scene delegate: Ensure scene(_:openURLContexts:) is implemented
  4. Check URI format: Verify deep link starts with your registered scheme

Security Best Practices

  1. Protect API Keys:

    • Never commit actual TDWriteKey to source control
    • Use placeholder values in Info.plist committed to Git
    • Document required configuration separately
    • Use write-only keys (not master keys)
    • Consider using Keychain for production apps
  2. Validate Deep Links:

    • Always validate deep link destinations before navigating
    • Implement URL allowlists for sensitive actions
    • Sanitize deep link parameters
  3. Secure Event Data:

    • Do not include PII (personally identifiable information) in event payloads
    • Use hashed or anonymized user IDs when possible
  4. Network Security:

    • Always use HTTPS for API endpoints
    • Implement App Transport Security (ATS)
    • Consider certificate pinning for production apps

Sample Repository

Complete, production-ready implementation:

https://github.com/treasure-data/engage-push-notification-sample/tree/main/ios

The repository includes:

  • Full source code with inline documentation
  • XcodeGen project configuration
  • Swift Package Manager dependency management
  • Treasure Data SDK integration examples
  • Testing instructions
  • Security best practices

Implementation Guide

This section provides detailed instructions for building and testing the sample application.

Project Structure

The sample repository follows this directory structure:

ios/
├── TDPushSample/
│   ├── AppDelegate.swift           # Firebase & TD SDK init, notification delegates
│   ├── SceneDelegate.swift         # Deep link routing
│   ├── ViewController.swift        # Main UI
│   ├── TrackingService.swift       # Event tracking with TD SDK
│   ├── CategoryView.swift          # Category example
│   ├── ProductDetailView.swift     # Product detail example
│   ├── Models/                     # Data models
│   ├── Utils/                      # Utility classes
│   ├── Assets.xcassets
│   ├── Info.plist                  # App config & TD settings
│   └── GoogleService-Info.plist.example  # Firebase config template
├── NotificationService/             # Extension for rich media
│   └── NotificationService.swift
├── project.yml                      # XcodeGen configuration
└── TDPushSample.xcodeproj/         # Generated by XcodeGen

Build and Run Instructions

Prerequisites

  • macOS 12.0 or later
  • Xcode 14.0 or later
  • XcodeGen installed via Homebrew

Setup Steps

  1. Clone the repository:
git clone https://github.com/treasure-data/engage-push-notification-sample.git
cd engage-push-notification-sample/ios
  1. Install XcodeGen (if not already installed):
brew install xcodegen
  1. Generate Xcode project:
xcodegen generate
  1. Configure Firebase:

    • Download GoogleService-Info.plist from your Firebase project
    • Copy it to TDPushSample/GoogleService-Info.plist
  2. Configure Treasure Data:

    • Open TDPushSample/Info.plist
    • Update the following keys with your configuration:
      • TDWriteKey: Your write-only API key
      • TDDatabase: Your database name (e.g., "mobile")
      • TDTable: Your table name (e.g., "push_events")
      • TDEndpoint: Your TD endpoint (e.g., "https://in.treasuredata.com")
  3. Open project in Xcode:

open TDPushSample.xcodeproj
  1. Build and run:
    • Select target device/simulator
    • Press Cmd+R to build and run
    • Swift Package Manager will automatically resolve dependencies

Testing Workflow

Prerequisites

Before testing, ensure you have:

  • Firebase project with iOS app registered
  • APNs authentication key uploaded to Firebase Console
  • GoogleService-Info.plist downloaded and added to project
  • Treasure Data database and table created
  • Write-only API key obtained
  • Physical device or iOS 13+ simulator

Test on Simulator (iOS 13+)

  1. Create test payload file test-notification.apns:
{
  "Simulator Target Bundle": "com.example.myapp",
  "aps": {
    "alert": {
      "title": "Test Notification",
      "body": "This is a test message"
    },
    "sound": "default",
    "badge": 1
  },
  "campaign_id": "test_campaign",
  "deeplink": "myapp://test",
  "image_url": "https://example.com/image.jpg"
}
  1. Run app on simulator:
# Boot simulator
xcrun simctl boot "iPhone 15"

# Build and run
xcodebuild -workspace MyApp.xcworkspace \
  -scheme MyApp \
  -destination 'platform=iOS Simulator,name=iPhone 15' \
  build
  1. Send test notification:
xcrun simctl push booted com.example.myapp test-notification.apns
  1. Verify notification appears and image loads

Test on Physical Device

  1. Connect device via USB

  2. Enable Developer Mode on device:

    • Settings > Privacy & Security > Developer Mode
  3. Build and install app from Xcode

  4. Check Xcode console for FCM token:

FCM token: [your-token-here]
  1. Send test notification from Firebase Console:

    • Open Firebase Console > Cloud Messaging
    • Click "Send your first message"
    • Enter title and body
    • Click "Send test message"
    • Paste your FCM token
    • Click "Test"
  2. Verify notification appears on device

Verify Event Tracking

Query Treasure Data to confirm events are being logged:

SELECT
  time,
  type,
  campaign_id,
  platform,
  user_id
FROM mobile.push_events
WHERE platform = 'ios'
  AND time > td_time_add(now(), '-1h', 'JST')
ORDER BY time DESC
LIMIT 20

Expected event sequence:

  1. token_register - When app launches
  2. delivery - When notification is received
  3. open - When user taps notification
  4. link_open or deeplink_open - If notification contains links

Implementation Checklist

Use this checklist when implementing push notifications in your own app:

Phase 1: Project Setup

  • Install XcodeGen: brew install xcodegen
  • Create or clone iOS project
  • Generate Xcode project with xcodegen generate
  • Add Push Notifications capability in Xcode
  • Add Background Modes capability (Remote notifications)
  • Configure URL scheme for deep links in Info.plist
  • Download and add GoogleService-Info.plist
  • Configure Treasure Data settings in Info.plist

Phase 2: Core Components

  • Implement Firebase initialization in AppDelegate
  • Implement Treasure Data SDK initialization in AppDelegate
  • Configure UNUserNotificationCenter delegate
  • Configure Firebase Messaging delegate
  • Request notification permissions
  • Register for remote notifications
  • Create TrackingService for event tracking with TD SDK

Phase 3: Notification Service Extension

  • Create Notification Service Extension target
  • Implement NotificationService class
  • Add image download logic
  • Create UNNotificationAttachment for images
  • Handle extension timeout gracefully

Phase 4: Event Tracking

  • Track delivery events in willPresent delegate using TD SDK
  • Track open events in didReceive response delegate using TD SDK
  • Track dismiss events for dismissed notifications using TD SDK
  • Track link_open events for web links using TD SDK
  • Track deeplink_open events for app links using TD SDK
  • Track token_register events on app launch and token refresh using TD SDK
  • Implement scene(_:openURLContexts:) in SceneDelegate
  • Parse deep link URL scheme and path
  • Navigate to appropriate screen based on deep link
  • Handle web links with Safari or SFSafariViewController
  • Validate deep link destinations

Phase 6: Configuration and Security

  • Configure TDWriteKey, TDDatabase, TDTable, TDEndpoint in Info.plist
  • Use placeholder values for API keys in version control
  • Document required configuration separately
  • Implement error handling for TD SDK operations
  • Add logging for debugging using TreasureData.enableLogging()

Phase 7: Testing

  • Test notification delivery on simulator
  • Test notification delivery on physical device
  • Test rich media (images) in notifications
  • Test deep link navigation
  • Test web link opening
  • Verify events appear in Treasure Data
  • Test with background app state
  • Test with force-quit app state

Build Troubleshooting

"No such module 'Firebase'" or "No such module 'TreasureData'" Error

  • Ensure Swift Package Manager resolved dependencies
  • Try: File > Packages > Reset Package Caches
  • Clean build folder: Product > Clean Build Folder (Cmd+Shift+K)
  • Regenerate project: xcodegen generate

Notification Service Extension Not Loading Images

  • Check image URL is HTTPS
  • Verify image is accessible (test URL in browser)
  • Check extension logs in Console.app
  • Ensure extension target has increased memory limit in scheme settings

Events Not Appearing in Treasure Data

  • Verify TDWriteKey in Info.plist is correct
  • Check TDEndpoint matches your region
  • Confirm TDDatabase and TDTable names are correct
  • Verify TD SDK is initialized in AppDelegate
  • Enable logging: TreasureData.enableLogging()
  • Force upload: TreasureData.sharedInstance().uploadEvents()
  • Verify URL scheme in Info.plist matches deep link
  • Test deep link from Safari: enter myapp://test in address bar
  • Check scene(_:openURLContexts:) is implemented in SceneDelegate
  • For iOS 12 and below, implement in AppDelegate instead

Next Steps

  1. Clone the sample repository and review the implementation
  2. Configure Firebase following the Mobile Push Setup guide
  3. Implement the components in your iOS app
  4. Test notification delivery and event tracking
  5. Review event data in the Push Events Table
  6. Create your first campaign in Engage Studio