Actual Activation Overview
What is BlinkEngage?
BlinkEngage is the SDK for Actual's Activation Platform. This SDK sits on top of the BlinkReceipt SDK (Paper Receipt) and adds rewards, offers, and ad monetization to your receipt scanning flow. BlinkEngage takes over after the scan — loading screen, receipt summary, boost ads, the works.
What It Does
Out-of-the-box User Activation Journeys
The SDK supports five distinct user journeys, each representing a different way users can engage and earn rewards:
| Journey | Description |
|---|---|
| Offer Discovery & Clipping | Browse and clip available offers |
| Receipt Scanning | Scan receipts to earn on qualifying purchases |
| Receipt Boosters (Watch & Earn) | Watch ads for bonus rewards |
| Product Capture UGC Tasks (Snap & Earn) | Photograph products for extra rewards |
| Missed Earnings | Correct receipt data for potential credits |
Offer Wall
A pre-built screen that shows coupons and deals to your users. Supports grid, list, and carousel layouts and controlled server side by Actual with dynamic capabilities. Users can filter by store, clip offers to save them, and kick off a receipt scan from a floating action button.
The offer wall manages requirements for offer details and catalogue management on behalf of the publisher app. It should be presented in a regularly accessible location within the host app. Ideally dedication navbar location. Future versions will enable widget creation for placement in the broader host app with deeplinking to offer wall.
Two modes:
.all— Every available offer.clipped— Only what the user saved
Receipt Scanning
Engage your users and collect valuable purchase data. Actual fully-manages the user experience and data extraction of scanning a paper receipt from any retailer and turning it into structured data.
Receipt Boosters and Product Capture
Once a user successfully scans a receipt, we'll keep them engaged with more ways to earn (and drive revenue for you) such as watching targeted ads (Watch & Earn) or snapping product labels and barcodes (Snap & Earn).
Missed Earnings
For users who have challenges with receipt submission or reward redemption, we provide an out-of-the-box flow for users to re-submit their receipt to claim any missed earnings.
Rewards
You configure three properties and the SDK handles the rest:
rewardCurrencyName— What to call your currency ("points", "coins", etc.). Default:"pts"rewardCurrencyPerDollar— Conversion rate. Default:100.0($1 = 100 points)userPayoutPercentage— Share of boost/UGC rewards the user gets (40%–100%). Default:0.6. In current versions, this is a shared property. Best practice guidance is to use the default 60%.
Theming
Implement the Theme protocol to swap out colors, fonts, and icons across every screen. Return nil for any key to keep the SDK default. See the iOS Activation Customization guide for the full reference of color, font, and icon keys.
How the Scan Flow Works
1. User Scans a Receipt
You start the BlinkReceipt camera as usual. When enableBlinkEngage = true, the SDK takes it from there — no need to handle scan results yourself.
2. Loading Screen
While the backend processes the receipt, users see a loading drawer with a progress bar and an ad slot (native or banner). The progress runs in two stages: 0%→80% while waiting for data, then 80%→100% when results come back.
Status messages rotate through: "Scanning receipt", "Qualifying purchases", "Loading offers".
3. Receipt Summary Screen
Shows what the user earned:
| Reward Type | What It Is |
|---|---|
| Base Scan Reward | Points your app assigns for completing a scan (via rewardCallback)Webhook: base_scan |
| PVP Offer Rewards | Points earned (with statuses streamed back via webhook) for promotions related to purchased items on the receipt Webhook: promo |
| Boost Rewards | Bonus points from watching a rewarded video ad Webhook: boost |
| UGC Task Rewards | Points paid by Actual for scanning a product barcode and taking a photo Webhook: barcode_collection |
The reward counter animates from 0 to the total, followed by a confetti effect. Qualified products get highlighted in the list.
4. Boost Opportunities
After the summary loads, users can earn more by:
- Watching a short video ad
- Completing a CPA offer (survey, app install, etc.)
- Scanning a product barcode for a UGC task
5. Missed Earnings
If user feels they were not granted a reward for something they expected, they can submit a claim to remedy it:
- Tap the receipt icon on the summary header
- Edit merchant name (with auto-suggest), date (inline picker), or product details
- Add missing products by scanning their barcode
- Submit — corrected items turn green and show "Pending Review"
Reward Callback
Your app needs to implement one closure on BlinkEngageSDK.shared.rewardCallback. While your primary accounting should be based on webhook, these callbacks are provided for the sake of UI continuity immediately after the scan and we advise you reconcile it with the webhook when the webhook is received.
It gets called in four situations:
| Context | Who's Talking | What To Do |
|---|---|---|
"ScanFinished" | SDK asks your app | Return an NSNumber with the base scan reward |
"Promo" | SDK tells your app | Credit rewardAmount to the user |
"Boost" | SDK tells your app | Credit rewardAmount to the user |
"BarcodeCollection" | SDK tells your app | Credit rewardAmount to the user |
If you don't set this callback, base scan reward defaults to 0. The SDK still calculates and displays promo/boost/UGC rewards on screen, but your app won't know to credit them.
BlinkEngageSDK.shared.rewardCurrencyName = "points"
BlinkEngageSDK.shared.rewardCurrencyPerDollar = 100.0
BlinkEngageSDK.shared.userPayoutPercentage = 0.5
Reward Examples
Base Scan Reward
- BlinkEngage SDK invokes the
rewardCallbackto ask host app how much to reward for the current scan - Host app responds with a number specifying the base scan reward (if any) in in-app currency
- This amount is used in 2 ways:
- It is displayed (along with any other rewards) in the Receipt Summary Screen (RSS) to indicate to the user how many points they received for the current scan
- It is converted to a dollar amount by dividing by your
currencyPerDollarsetting and then this dollar amount is sent to your webhook
- The
userPayoutPercentageproperty has no impact on this reward type - Example:
- User finishes scan
- BlinkEngage SDK calls
rewardCallbackwithcontext=ScanFinished - Host app returns
1500 - BlinkEngage displays 1500 Points at the top of the RSS
- Webhook sent with
rewardValue: 15.00
Offer Validations
- All SKU-based offers have a fixed dollar amount associated with them, which must be paid out entirely to the user
- Thus, when a user opens the offer wall in your app, BlinkEngage takes the dollar amount of each offer, multiplies by your
currencyPerDollarand displays the resulting points value in the card for each offer - When a user scans a receipt with qualifying products for a given offer, the user sees the corresponding points value on the RSS in-line with the qualifying product
- The webhook sent to your backend contains the dollar amount for that offer
- The
userPayoutPercentagehas no impact on this reward type - Example:
- An offer for Colgate Toothpaste has a dollar value of $2
- The user sees this offer on the offer wall as 200 points
- If the offer scans a qualifying receipt, on the RSS they will see 200 points next to that line item
- BlinkEngage SDK calls
rewardCallbackwithcontext=PromoandrewardAmount=200 - Webhook sent with
rewardValue: 2.00for this offer
Boosts (Watch & Earn / Snap & Earn)
- On the RSS we will occasionally present the user with opportunities to “boost” their rewards for that receipt by either watching a rewarded ad (Watch & Earn), or performing a product collection task (Snap & Earn - i.e. snap a picture of the product and scan its barcode)
- We set the dollar reward amount for these boosts, and we multiply them by both
currencyPerDollarANDuserPayoutPercentage(if any) to determine the number of points to show alongside the boost CTA - The webhook sent to your backend contains the dollar amount for the boost
- Example:
- A Watch & Earn boost has a reward value of $1
- User sees this CTA on the Receipt Summary Screen as 50 points ($1 x 100 x 0.5)
- The user successfully watches the ad
- User sees 50 points added to their tally on the Receipt Summary Screen
- BlinkEngage calls
rewardCallbackwithcontext=BoostandrewardAmount=50 - Webhook is sent with
rewardValue: 1.00
Error Screens
The SDK shows an error modal instead of the Receipt Summary when something goes wrong. Once the user dismisses the error message modal, they can start a new scan session. These are the possible errors:
| What Happened | Title Shown | Trigger |
|---|---|---|
| Already scanned | "Receipt already scanned" | Duplicate detected server-side |
| Too old | "Receipt too old" | Purchase date > 14 days ago |
| Fake receipt | "Invalid Receipt" | Fraud flags or failed on-device receipt check |
| Network issue | "Oops!" | API timeout or failure |
| Too many scans | "Receipt limit reached" | User hit daily/weekly submission caps |
Fraud reasons on our back-end that trigger rejection: receipt_counterfeit_text, receipt_merchant_mismatch, user_geo_anomaly, user_identity_anomaly, ip_anomaly.
Debug Mode
For development, turn on test ads so you don't serve real ones:
BlinkEngageSDK.shared.debugModeEnabled = true
Turn this off before shipping.
Architecture
The SDK is organized into self-contained modules:
| Module | What It Does |
|---|---|
OfferWallScreen | Offer display, store filtering, clipping |
AdLoadingScreen | Loading drawer with progress bar and ad slot |
ReceiptSummaryScreen | Scan results, rewards, boost offers |
MissedEarningsScreen | Receipt correction UI |
StoresScreen | Store list and filtering |
ProductCaptureScreen | Barcode scanning and photo capture for UGC |
Patterns used: MVVM for each module, a Coordinator layer (Combine-based) for presentation flow, and a shared service layer for networking, image caching, logging, and Google Ads.
Network handling: built-in NWPathMonitor for connectivity checks, and URLSession configured with waitsForConnectivity = true.