Core concepts
Six ideas appear in every module. Learn them once here and the API reference reads easily.
virtualId — the user identity
virtualId is your pseudonymous identifier for a user. Cheggout never receives your customer's
real identity.
| Property | Requirement |
|---|---|
| Owned by | The publisher. You generate it. |
| Uniqueness | Unique per user within your channel |
| Stability | Immutable — must not change for that user, ever |
| PII | Must not embed personal data (no raw email, mobile number or account number) |
A virtualId must be immutable and must never be reassigned to a different person. Everything
Cheggout holds for a user — reward history, coupons, eligibility and frequency caps — is keyed on
it, so changing it or handing it to someone else is not recoverable from your side.
{ "virtualId": "pub_8f14e45fceea167a" }
If you reassign a virtualId to a different person, that person inherits the previous user's
rewards and coupons. Treat it as permanently burned once issued.
The iOS SDK names its launch parameter userID rather than virtualId, but it carries this same
value.
CHANNELID / channelName — who you are
Your channel is your publisher identity on the platform, issued by Cheggout during onboarding. It appears as:
CHANNELIDin signed request envelopesX-CHANNELIDas an HTTP header on Deals Store APIschannelName/bNameinside request payloadschannelNameas a query parameter on widget and hosted URLs
It is an identifier, not a secret. It tells Cheggout which public key to verify your signature with, which campaigns apply, and which theme to use. Authentication comes from the signature or API key that accompanies it — never from the channel value alone.
The same value is called bName in one payload and channelName in another, and some payloads
match keys case-sensitively. Each API reference page states the exact key that endpoint expects.
Follow the page, not the pattern.
Placements — where things appear
A placement is a slot in your UI that Cheggout can fill. You integrate the slot once; Cheggout decides what goes in it and can change that at any time without an app release.
Placements are addressed by placementId — for example "01" for a banner position and "00" for
the store row. Which IDs are valid for your channel is configured during onboarding.
TBD The full placement registry is not yet published. There is no
self-service list of valid placementId values or a way to create placements yourself. Ask your
Cheggout contact for your channel's placement map. Tracked in
Open Items.
Trigger events — what happened
A trigger event tells Cheggout that a rewardable thing occurred. It is a predefined code agreed with Cheggout, not free text, and it maps to a campaign on Cheggout's side.
| Surface | Parameter | Examples seen in integrations |
|---|---|---|
| Mobile SDK | triggerEventType | Payment-type codes such as UPI, IMPS, RTGS, WITHINBANK; channel-prefixed variants also exist |
| Headless API | triggerEventType | Channel-specific campaign codes |
| Web widget | eventType | CAMPAIGN_ARTICLEREAD; the current examples also use the lowercase form article_read |
Some flows also accept subTriggerEventType for a finer-grained sub-category.
TBD The authoritative trigger-code registry is not published. Codes differ by publisher and module, and the examples in circulation are inconsistent. Your codes are assigned during campaign setup — see Trigger events.
extTransactionId — idempotency and reconciliation
For any event that can produce a reward or a coupon, you supply extTransactionId: your own unique
reference for that event.
| Property | Requirement |
|---|---|
| Owned by | The publisher |
| Uniqueness | Globally unique. Never reused. |
| Format | Alphanumeric, maximum 256 characters |
| Purpose | Idempotency key, and the join key for reconciliation and dispute resolution |
A sensible format encodes the source and the moment:
PUB_OFFERBUY_20260213_000045
Replaying the same extTransactionId is how you retry safely after a network failure. Read the
idempotency guidance before you rely on it — the guarantees
differ by module and there are documented exceptions.
Tracking links
Cheggout returns tracking URLs alongside every reward, banner and store item. They arrive in one of two shapes.
As arrays, on rewards APIs:
{
"trackLink": ["https://tracking.cheggout.com/Tracker/Impression?..."],
"clicktrack": ["https://tracking.cheggout.com/Tracker/clicks?..."]
}
As a tagged string, on banner and store APIs — a pseudo-XML envelope carrying several URLs plus display metadata:
<click>https://example.com/destination</click>
<track>https://tracking.cheggout.com/...Impression...</track>
<clicktrack>https://tracking.cheggout.com/...clicks...</clicktrack>
<browser>Native</browser>
<expiryduration>60</expiryduration>
<id>placement_channel_unit</id>
<redirectURL>...</redirectURL>
The mobile SDKs parse this for you. If you are integrating headlessly, parse out the tag you need and fire the URLs directly with a plain GET.
The contract is simple and non-negotiable:
- Fire impression URLs when the item becomes visible to the user.
- Fire click URLs when the user taps or scratches it.
Attribution, billing and your reporting all derive from these calls. An integration that renders correctly but never fires tracking is not finished.
Putting it together
{
"channelName": "YOURCHANNEL",
"virtualId": "pub_8f14e45fceea167a",
"triggerEventType": "YOURCHANNEL_CAMPAIGN",
"extTransactionId": "PUB_TXN_20260731_000117",
"amount": 499.00,
"dateandtime": "31072026141530"
}
Your channel, your user, what happened, your unique reference for it. Everything else — whether a reward exists, which one, and whether this user has had too many already — is Cheggout's decision.