iOS Activation Prerequisites
Everything you need before you start writing code.
1. Credentials & Keys
All three are provided by Actual — the client does not create or manage these. Reach out to your account representative if you don't have them.
| Key | Where It Goes | Provided By | Required? |
|---|---|---|---|
| BlinkReceipt License Key | BRScanManager.shared().licenseKey | Actual | Yes |
| Product Intelligence Key | BRScanManager.shared().prodIntelKey | Actual | Technically optional, but required for usable product data |
| Google Ad Manager 360 App ID | Info.plist → GADApplicationIdentifier | Actual | Yes (for ads). You must use the AppID provided by your Actual account team. |
The Google Ad Manager 360 App ID and all ad unit IDs are managed by Actual . You do not need your own GAM360 account. Ad unit IDs are delivered to the SDK automatically from the BlinkEngage backend — the client only needs to drop the App ID into their Info.plist. See the GAM MCM Setup guide for account configuration.
The license key and prod intel key are separate. The license key gates access to the scanning engine. The prod intel key unlocks product intelligence — the service that matches raw receipt text to a product database and returns structured data (full product name, brand, category, UPC).
Without the prod intel key, the SDK can only return whatever text the OCR pulled off the receipt. Here's what that looks like in practice:
| Without Prod Intel (raw OCR) | With Prod Intel (enriched) | |
|---|---|---|
| Product name | GV CHED GOLDFISH CRK 6.6Z | Pepperidge Farm Goldfish Cheddar Crackers, 6.6 oz |
| Brand | (empty) | Pepperidge Farm |
| Category | (empty) | Snacks / Crackers |
| UPC | (empty) | 014100096252 |
The raw OCR text is what appears on the Receipt Summary Screen if prod intel is not configured. For any production integration, treat the prod intel key as required.
2. System Requirements
| Minimum | |
|---|---|
| iOS | 15.0+ |
| Swift | 5.9+ |
| Xcode | 16.4+ |
3. SDK Dependencies
BlinkReceipt SDK
BlinkEngage does not include a scanner. It sits on top of the BlinkReceipt SDK, which provides the camera UI, OCR, and on-device processing.
If you install BlinkEngage via SPM, BlinkReceipt is declared as a package dependency and gets resolved automatically — you don't need to add it separately. If you use CocoaPods, you may need to add BlinkReceipt as a separate pod. Either way, complete the standard BlinkReceipt integration (camera permissions, license key) before moving on to BlinkEngage setup:
BlinkEngage SDK
Swift Package Manager (recommended):
- In Xcode → File → Add Package Dependencies
- Enter:
https://github.com/BlinkReceipt/blinkengage-ios - Add the BlinkEngage product
This automatically pulls in BlinkReceipt and Google-Mobile-Ads-SDK as transitive dependencies.
CocoaPods:
pod 'BlinkEngage', '~> 1.7.0'
Then run pod install.
4. Info.plist Entries
Google Ad Manager 360 (required for ads)
Add your Ad Manager 360 App ID. Without this, the app will crash on ad load. See the GAM MCM Setup guide for account configuration.
<key>GADApplicationIdentifier</key>
<string>YOUR-GAM-APP-ID</string>
Camera Permission (required for scanning)
BlinkReceipt uses the camera for receipt scanning. BlinkEngage also uses it for the barcode scanner in the Missed Earnings and UGC product capture flows:
<key>NSCameraUsageDescription</key>
<string>This app uses the camera to scan receipts and product barcodes.</string>
SKAdNetwork (recommended for ad attribution)
Google Ad Manager 360 requires SKAdNetwork identifiers for proper ad attribution. Follow the Google Mobile Ads SDK docs to add the required SKAdNetworkItems to your Info.plist.
5. AppDelegate Setup
Everything goes in application(_:didFinishLaunchingWithOptions:). Order matters — BlinkEngageSDK.start(debugMode:) must be called before any BRScanManager.shared() calls.
import BlinkEngage
import BlinkReceipt
import GoogleMobileAds
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// --- BlinkEngage bootstrap (call before any BRScanManager.shared() calls) ---
#if DEBUG
BlinkEngageSDK.start(debugMode: true)
#else
BlinkEngageSDK.start(debugMode: false)
#endif
// --- BlinkReceipt ---
BRScanManager.shared().licenseKey = "YOUR-LICENSE-KEY"
BRScanManager.shared().prodIntelKey = "YOUR-PROD-INTEL-KEY"
// --- Google Mobile Ads ---
MobileAds.shared.start()
// Register test devices so GAM360 serves test ads on real hardware during development.
// Find your device ID in the Xcode console when a real ad request runs.
MobileAds.shared.requestConfiguration.testDeviceIdentifiers = ["YOUR-TEST-DEVICE-ID"]
// User identity — at least one hash is required for registration
BlinkEngageSDK.shared.user.emailHash = "sha256_of_user_email"
// or: BlinkEngageSDK.shared.user.phoneHash = "sha256_of_user_phone"
// Optional: your own user ID for mapping
BlinkEngageSDK.shared.user.clientUserId = "your_internal_user_id"
// Reward configuration
BlinkEngageSDK.shared.rewardConfig = BlinkEngageRewardConfig(
currencyName: "points",
currencyPerDollar: 100.0,
userPayoutPercentage: 0.6,
rewardCallback: { context, rewardAmount, blinkReceiptId in
switch context {
case "ScanFinished":
return NSNumber(value: 10)
case "Promo", "Boost", "BarcodeCollection":
// credit rewardAmount to user
return nil
default:
return nil
}
}
)
// Optional: theming
BlinkEngageSDK.shared.appearance = Appearance(theme: MyTheme())
// Optional: client event tracking
BlinkEngageSDK.shared.eventCallback = { eventName, metadata in
// forward to your analytics system
}
return true
}
6. User Identity
The SDK needs a hashed user identifier to register with the backend. Set at least one before any scan occurs:
BlinkEngageSDK.shared.user.emailHash = "sha256_hash"
// or
BlinkEngageSDK.shared.user.phoneHash = "sha256_hash"
When either is set, the SDK automatically registers the user with the BlinkEngage API. No manual registration call needed.
clientUserId is optional — use it if you want to map BlinkEngage activity back to your own user IDs:
BlinkEngageSDK.shared.user.clientUserId = "your_id"
7. What scanOptions.enableBlinkEngage = true Changes
Set enableBlinkEngage = true on the BRScanOptions instance you pass into each scan session where monetization should run. When enabled, BlinkReceipt's behavior changes for that session:
- The
didFinishScanning:withScanResults:delegate callback still fires, butscanResultsis alwaysnil. BlinkEngage intercepts the results internally. - BlinkReceipt alerts BlinkEngage when the scan session begins, ends, and results are available.
- BlinkEngage takes over after the camera dismisses — it shows the loading screen, calls the backend, and presents either the Receipt Summary Screen or an error screen.
func startScan() {
let scanOptions = BRScanOptions()
scanOptions.enableBlinkEngage = true // enables post-scan flow for this session
BRScanManager.shared().startStaticCamera(
from: self,
cameraType: .standard,
scanOptions: scanOptions,
with: self
)
}
Leave enableBlinkEngage at its default (false) for any scan session that should not trigger the BlinkEngage post-scan flow. You still own the camera — you call BRScanManager.shared().startStaticCamera(...) and implement BRScanResultsDelegate for didCancelScanning:.
8. Reward Configuration Quick Reference
Reward configuration is set via BlinkEngageRewardConfig and assigned to BlinkEngageSDK.shared.rewardConfig:
| Parameter | Default | What It Controls |
|---|---|---|
currencyName | "points" | Label shown next to reward amounts (e.g. "points", "gems") |
currencyPerDollar | 100.0 | Converts dollar payouts to your currency ($1 = 100 pts) |
userPayoutPercentage | 0.6 | Share of boost/UGC rewards the user gets (clamped to 0.4–1.0) |
rewardCallback | nil | Called on each reward event — return NSNumber for "ScanFinished", nil for others |
BlinkEngageSDK.start(debugMode: true) tells the BlinkEngage backend to return test ad unit IDs. testDeviceIdentifiers on Google's SDK serves test creatives on specific physical devices. During development you typically want both.
See Reward Currency for the full BlinkEngageRewardConfig reference, including label styles, messaging styles, custom icons, and Objective-C usage.
9. Theming (Optional)
Implement the Theme protocol to customize colors, fonts, and icons. Return nil for any key to keep the SDK default. Pass Appearance(theme: nil) to use all defaults.
The protocol has seven members:
isRewardIconEnabled: Bool— Show/hide the default reward iconisMerchantIconEnabled: Bool— Show/hide merchant logos on the Stores screenglobalFontMatrix: NSDictionary?— Map font weights to font names (fallback whenfontName(forKey:)returns nil)color(forKey:) -> UIColor?— Custom colors byAppearanceColorKeyfontName(forKey:) -> String?— Custom font names byAppearanceFontNameKeyimage(forKey:) -> UIImage?— Custom images byAppearanceIconKeytext(forKey:) -> String?— Custom strings byAppearanceTextKey(e.g. floating button labels)
10. Checklist
Before you start coding, confirm:
- BlinkReceipt SDK installed and scanning works on its own
- BlinkReceipt license key obtained and working
- Product Intelligence key obtained (needed for readable product names)
- Google Ad Manager 360 account set up, App ID in Info.plist (see GAM MCM Setup)
- SKAdNetwork identifiers added to Info.plist (for ad attribution)
NSCameraUsageDescriptionin Info.plist- BlinkEngage SDK added via SPM or CocoaPods
- At least one user identifier ready (hashed email or phone)
- Reward currency name and conversion rate decided
rewardCallbackimplemented (even a stub that returns 0)