Mobile Push is currently in beta. Features, APIs, and implementation details may change before general availability.
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:
- APNs/FCM Integration: Receive push notifications via Apple Push Notification Service and Firebase Cloud Messaging
- Token Management: Register and update device tokens with Treasure Data
- Rich Notifications: Display notifications with images using Notification Service Extension
- Event Tracking: Track user interactions (delivery, open, dismiss, links) using Treasure Data SDK
- Automated Data Upload: Treasure Data SDK automatically handles event upload to Treasure Data
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.
| Component | Requirement |
|---|---|
| Minimum iOS Version | iOS 15.0 or later |
| Language | Swift (recommended) or Objective-C |
| Required Frameworks |
|
| Xcode Version | Xcode 14.0 or later |
| Tracked Events | delivery, open, dismiss, deeplink_open, link_open, token_register |
Your iOS app implementation consists of the following components:
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
Purpose: Download and attach images to notifications
Key Responsibilities:
- Receive notification before display
- Extract
image_urlfrom payload - Download image from remote URL
- Create UNNotificationAttachment
- Add attachment to notification content
Reference: See NotificationService.swift in the sample repository
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, anddeeplink_openevents - 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
The sample app uses XcodeGen to generate the Xcode project. Install XcodeGen:
brew install xcodegenGenerate the Xcode project:
cd ios
xcodegen generateThe project uses Swift Package Manager for dependency management. Dependencies are defined in project.yml:
Firebase iOS SDK (12.7.0+):
FirebaseMessagingFirebaseAnalytics
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.
Download
GoogleService-Info.plistfrom Firebase ConsoleCopy the file to your project:
cp GoogleService-Info.plist ios/TDPushSample/GoogleService-Info.plistEnsure the file is added to your main app target in Xcode
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.
- Select your project in Project Navigator
- Select your app target
- Go to Signing & Capabilities tab
- Click + Capability and add:
- Push Notifications
- Background Modes → Check Remote notifications
To support images in notifications, you need a Notification Service Extension:
- In Xcode, go to File > New > Target
- Select Notification Service Extension
- Enter extension name (e.g.,
NotificationService) - 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>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"
}| Field | Type | Required | Description |
|---|---|---|---|
td_campaign_id | String | Yes | Unique campaign identifier from Engage Studio |
title | String | Yes | Notification title |
body | String | Yes | Notification body text |
image_url | String | No | URL for rich notification image |
link | String | No | Web URL to open in Safari |
Your app must track the following events and send them to Treasure Data:
| Event Type | When to Track | Required Fields |
|---|---|---|
delivery | When notification is received and displayed | campaign_id, platform, time |
open | When user taps the notification | campaign_id, platform, time, user_id |
dismiss | When user dismisses the notification | campaign_id, platform, time, user_id |
link_open | When user taps a web link | campaign_id, platform, time, user_id, value (URL) |
deeplink_open | When user taps a deep link | campaign_id, platform, time, user_id, value (URI) |
token_register | When FCM token is obtained or refreshed | fcm_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.
iOS Simulator supports push notifications from iOS 13 and Xcode 11.4+:
- 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"
}- Send to simulator:
xcrun simctl push booted com.example.myapp test-notification.apns- Get your FCM token from app logs
- Open Firebase Console > Cloud Messaging
- Click Send your first message
- Enter title and body
- Click Send test message
- Enter your FCM token
- Verify notification appears on device
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 100To 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
nilforuser_id— Treasure Data will associate the token later when the user logs in - Name resolution: Treasure Data links events by matching
fcm_tokenvalues over time
- Check APNs certificate: Verify APNs authentication key is uploaded to Firebase Console
- Check Bundle ID: Ensure Bundle ID in Xcode matches Firebase registration (case-sensitive)
- Check notification permissions: Verify app has notification permission in Settings > Notifications
- Check device registration: Confirm
didRegisterForRemoteNotificationsWithDeviceTokenis called - Test with Firebase Console: Send test notification directly from Firebase
- Verify Notification Service Extension: Check extension is properly configured and added to app
- Check image URL: Ensure URL is HTTPS and image is accessible
- Check extension logs: Use Console.app to view extension logs
- Check file size: Large images may timeout (limit ~10MB)
- Check write key: Verify
TDWriteKeyin Info.plist is correct and active - Check endpoint: Ensure
TDEndpointmatches your region (US, Tokyo, EU) - Check table name: Confirm
TDDatabaseandTDTableexist in Treasure Data - Check SDK initialization: Verify Treasure Data SDK is initialized in AppDelegate
- Enable logging: Add
TreasureData.enableLogging()to see SDK activity - Force upload: Try calling
TreasureData.sharedInstance().uploadEvents()manually
- Verify URL scheme: Check
Info.plisthas correctCFBundleURLTypesconfiguration - Test deep link: Use Safari to test: Enter
myapp://testin address bar - Check scene delegate: Ensure
scene(_:openURLContexts:)is implemented - Check URI format: Verify deep link starts with your registered scheme
Protect API Keys:
- Never commit actual
TDWriteKeyto 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
- Never commit actual
Validate Deep Links:
- Always validate deep link destinations before navigating
- Implement URL allowlists for sensitive actions
- Sanitize deep link parameters
Secure Event Data:
- Do not include PII (personally identifiable information) in event payloads
- Use hashed or anonymized user IDs when possible
Network Security:
- Always use HTTPS for API endpoints
- Implement App Transport Security (ATS)
- Consider certificate pinning for production apps
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
This section provides detailed instructions for building and testing the sample application.
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- macOS 12.0 or later
- Xcode 14.0 or later
- XcodeGen installed via Homebrew
- Clone the repository:
git clone https://github.com/treasure-data/engage-push-notification-sample.git
cd engage-push-notification-sample/ios- Install XcodeGen (if not already installed):
brew install xcodegen- Generate Xcode project:
xcodegen generateConfigure Firebase:
- Download
GoogleService-Info.plistfrom your Firebase project - Copy it to
TDPushSample/GoogleService-Info.plist
- Download
Configure Treasure Data:
- Open
TDPushSample/Info.plist - Update the following keys with your configuration:
TDWriteKey: Your write-only API keyTDDatabase: Your database name (e.g., "mobile")TDTable: Your table name (e.g., "push_events")TDEndpoint: Your TD endpoint (e.g., "https://in.treasuredata.com")
- Open
Open project in Xcode:
open TDPushSample.xcodeproj- Build and run:
- Select target device/simulator
- Press Cmd+R to build and run
- Swift Package Manager will automatically resolve dependencies
Before testing, ensure you have:
- Firebase project with iOS app registered
- APNs authentication key uploaded to Firebase Console
-
GoogleService-Info.plistdownloaded and added to project - Treasure Data database and table created
- Write-only API key obtained
- Physical device or iOS 13+ simulator
- 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"
}- 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- Send test notification:
xcrun simctl push booted com.example.myapp test-notification.apns- Verify notification appears and image loads
Connect device via USB
Enable Developer Mode on device:
- Settings > Privacy & Security > Developer Mode
Build and install app from Xcode
Check Xcode console for FCM token:
FCM token: [your-token-here]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"
Verify notification appears on device
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 20Expected event sequence:
token_register- When app launchesdelivery- When notification is receivedopen- When user taps notificationlink_openordeeplink_open- If notification contains links
Use this checklist when implementing push notifications in your own app:
- 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
- Implement Firebase initialization in
AppDelegate - Implement Treasure Data SDK initialization in
AppDelegate - Configure
UNUserNotificationCenterdelegate - Configure Firebase Messaging delegate
- Request notification permissions
- Register for remote notifications
- Create
TrackingServicefor event tracking with TD SDK
- Create Notification Service Extension target
- Implement
NotificationServiceclass - Add image download logic
- Create
UNNotificationAttachmentfor images - Handle extension timeout gracefully
- Track
deliveryevents inwillPresentdelegate using TD SDK - Track
openevents indidReceive responsedelegate using TD SDK - Track
dismissevents for dismissed notifications using TD SDK - Track
link_openevents for web links using TD SDK - Track
deeplink_openevents for app links using TD SDK - Track
token_registerevents 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
- Configure
TDWriteKey,TDDatabase,TDTable,TDEndpointin 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()
- 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
- 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
- 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
- Verify
TDWriteKeyin Info.plist is correct - Check
TDEndpointmatches your region - Confirm
TDDatabaseandTDTablenames 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://testin address bar - Check
scene(_:openURLContexts:)is implemented in SceneDelegate - For iOS 12 and below, implement in AppDelegate instead
- Clone the sample repository and review the implementation
- Configure Firebase following the Mobile Push Setup guide
- Implement the components in your iOS app
- Test notification delivery and event tracking
- Review event data in the Push Events Table
- Create your first campaign in Engage Studio
- Mobile Push Setup - Firebase and APNs configuration
- Android Developer Guide - Android implementation guide
- Push Events Table - Event schema and analytics queries
- Campaign Creation - Create Mobile Push campaigns