Skip to main content

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:

JourneyDescription
Offer Discovery & ClippingBrowse and clip available offers
Receipt ScanningScan 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 EarningsCorrect 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 TypeWhat It Is
Base Scan RewardPoints your app assigns for completing a scan (via rewardCallback)
Webhook: base_scan
PVP Offer RewardsPoints earned (with statuses streamed back via webhook) for promotions related to purchased items on the receipt
Webhook: promo
Boost RewardsBonus points from watching a rewarded video ad
Webhook: boost
UGC Task RewardsPoints 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:

  1. Tap the receipt icon on the summary header
  2. Edit merchant name (with auto-suggest), date (inline picker), or product details
  3. Add missing products by scanning their barcode
  4. 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:

ContextWho's TalkingWhat To Do
"ScanFinished"SDK asks your appReturn an NSNumber with the base scan reward
"Promo"SDK tells your appCredit rewardAmount to the user
"Boost"SDK tells your appCredit rewardAmount to the user
"BarcodeCollection"SDK tells your appCredit 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 rewardCallback to 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 currencyPerDollar setting and then this dollar amount is sent to your webhook
  • The userPayoutPercentage property has no impact on this reward type
  • Example:
    • User finishes scan
    • BlinkEngage SDK calls rewardCallback with context=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 currencyPerDollar and 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 userPayoutPercentage has 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 rewardCallback with context=Promo and rewardAmount=200
    • Webhook sent with rewardValue: 2.00 for 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 currencyPerDollar AND userPayoutPercentage (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 rewardCallback with context=Boost and rewardAmount=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 HappenedTitle ShownTrigger
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:

ModuleWhat It Does
OfferWallScreenOffer display, store filtering, clipping
AdLoadingScreenLoading drawer with progress bar and ad slot
ReceiptSummaryScreenScan results, rewards, boost offers
MissedEarningsScreenReceipt correction UI
StoresScreenStore list and filtering
ProductCaptureScreenBarcode 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.