Offers
This guide covers the Toffee gCOM offer system, from fetching personalized offers to handling different types of promo engagements.
Offer Flow
Fetch an Offer
Request a personalized offer for a user based on their metadata and device information.
POST /toffee.v1.OfferService/FetchOffer
Authorization: Bearer <your_publishable_key>
Content-Type: application/json
{
"user_id": "player_42",
"user_metadata": {
"level": "15",
"achievements": "speedster,collector",
"playtime_hours": "120"
},
"user_devicedata": {
"id": "550e8400-e29b-41d4-a716-446655440000"
"model": "iPhone14,2"
"platform": "ios"
}
}
Parameters:
user_id: Unique identifier for the useruser_metadata: Key-value pairs containing user game data- Sample fields:
level,achievements,playtime_hours,last_purchase
- Sample fields:
user_devicedata: Key-value pairs containing device information- Sample fields:
id,model,platform,locale
- Sample fields:
Response
{
"id": "offer_abc123",
"url": "https://show.toffee.com/offer_abc123",
"image": "https://cdn.toffee.com/logos/special-offer.png",
"status": "available",
"expires": 3600
}
Response (No Offer Available)
{}
FetchOffer Response Fields
id: Unique identifier for the offerurl: URL to display in webview for the offer and checkout flowimage: URL or Base64-encoded image for the offer's logo/brandingstatus: Current status of the offer (available,shown,engaged)expires: Duration in seconds until the offer expires
Note: Provide relevant user metadata to get better targeted offers
Get an Offer
Retrieve a specific offer by its ID to get full offer details including status and timestamps.
POST /toffee.v1.OfferService/GetOffer
Authorization: Bearer <your_secret_key>
Content-Type: application/json
{
"id": "offer_abc123"
}
Response
{
"offer": {
"id": "offer_abc123",
"status": "shown",
"promo_id": "promo_xyz789",
"user_id": "player_42",
"game_id": "game_123",
"title": "Special Bundle Offer",
"description": "Get 50% off premium items",
"image": "https://cdn.toffee.com/offers/special-bundle.png",
"valid_from": "2023-06-01T00:00:00Z",
"valid_until": "2023-06-07T23:59:59Z",
"created_at": "2023-06-01T12:05:00Z",
"shown_at": "2023-06-01T14:22:00Z"
}
}
Offer Object Fields
id: Unique identifier for the offerstatus: Current status of the offer (see Offer Status Transitions below)promo_id: ID of the associated promo/promotionuser_id: ID of the user this offer is forgame_id: ID of the game this offer belongs totitle: Display title of the offerdescription: Detailed description of the offerimage: URL or Base64-encoded image for the offervalid_from: Start validity timestamp in ISO 8601 formatvalid_until: Expiration timestamp in ISO 8601 formatcreated_at: Creation timestamp in ISO 8601 formatshown_at: When the offer was shown to the user (optional)engaged_at: When the user engaged with the offer (optional)redeemed_at: When the offer was redeemed (optional)dismissed_at: When the offer was dismissed by user (optional)abandoned_at: When the offer was abandoned during checkout (optional)revoked_at: When the offer was revoked (optional)expired_at: When the offer expired (optional)
Get Promo by Offer
Retrieve the promo content associated with a specific offer. This endpoint is typically used by offer pages to fetch and display the appropriate promotional content.
POST /toffee.v1.OfferService/GetPromoByOffer
Authorization: Bearer <your_secret_key>
Content-Type: application/json
{
"offer_id": "offer_abc123"
}
Parameters:
offer_id: Unique identifier for the offer
Response
{
"promo": {
"id": "promo_xyz789",
"name": "Summer Special Bundle",
"type": "video",
"url": "https://cdn.toffee.com/videos/summer-bundle.mp4"
}
}
Response Fields:
promo: The promo object associated with the offerid: Unique identifier for the promoname: Display name for internal referencetype: Content type (video,image, oriframe)url: Location of the promo content
Offer Status Transitions
Offers progress through various states during their lifecycle:
Status Definitions
- available: Offer is created and ready to be shown
- shown: Offer has been displayed to the user
- engaged: User interacted with the offer (clicks, watches video, etc.)
- redeemed: User completed the offer (purchase, claimed rewards, etc.)
- dismissed: User actively dismissed the offer
- abandoned: User started but didn't complete the offer interaction
- revoked: Offer was revoked
- expired: Offer expired due to time limits
Webhook Events
Toffee sends webhooks to notify your backend when offer status transitions occur. See the Webhooks page for implementation details and signature verification.
Offer Events
offer.shown: When an offer is displayed to the useroffer.engaged: When user interacts with the offer (clicks, watches video, etc.)offer.redeemed: When user completes the offer (completes purchase, etc.)offer.dismissed: When user actively dismisses the offeroffer.abandoned: When user starts but doesn't complete the offer interactionoffer.revoked: When an offer is revokedoffer.expired: When an offer expires due to time limits
Display the Offer
Once you receive an offer, open the url in a webview within your game:
- Open Webview: Load the
urlin your game's webview - Load Content: The offer page fetches and loads content based on the promo type (video, image, or iframe)
- User Engagement: User interacts with the content according to the promo type
Promo Types & Engagements
Video/Image Promos:
- User must watch video for a minimum duration (e.g., 30 seconds)
- Engagement tracked via heartbeat calls sent to Toffee during video playback
- Status transitions:
shown→engaged(when watch threshold met) →redeemed(reward claiming)
Iframe Promos (Minishop):
- Embedded shopping experience within the offer page
- User can browse products and interact with the minishop
- Status transitions:
shown→engaged(user clicks buy now, enters email, etc.) →redeemed(purchase completion)
Handling Offer Events
The offer URL communicates key events back to your game through postMessage. These events work in both web iframes and native webviews (iOS/Android), allowing you to respond to user actions within the offer flow.
Note: Offer events are delivered through two channels:
- postMessage (client-side): For immediate UI actions like closing the webview or showing success messages
- Webhooks (server-side): For reliable server-side processing like awarding rewards. See the Webhook Events section below for details.
Available Events:
toffee_engage: Fired when the user engages with the offer (e.g., clicks buy now, enters email, starts interaction)toffee_redeem: Fired when the user successfully redeems/completes the offer (e.g., purchase completed, reward claimed)toffee_close: Fired when the offer page requests to be closed (e.g., user clicks close button, offer flow completed)
Listening for Events (Web/Iframe):
window.addEventListener('message', (event) => {
switch (event.data.type) {
case 'toffee_engage':
console.log('User engaged with the offer');
// Track engagement in your analytics
break;
case 'toffee_redeem':
console.log('User redeemed the offer');
// Award in-game rewards, refresh player inventory
break;
case 'toffee_close':
console.log('Offer page requested to close');
closeOfferPopup();
break;
}
});
Listening for Events (Native WebView):
For native mobile implementations (iOS/Android), configure your webview to intercept postMessage events. The messages have the same structure as web implementations with a type property:
{ "type": "toffee_engage" }
{ "type": "toffee_redeem" }
{ "type": "toffee_close" }
- iOS: Use
WKScriptMessageHandlerto receive postMessage events from the webview - Android: Configure WebView to handle postMessage events using JavaScript interfaces
The event handling logic remains the same—check event.data.type and respond accordingly.
Offer Validity
Offers have expiration times to ensure freshness and relevance:
- Expiration: FetchOffer response includes an
expiresfield with duration in seconds - Expired Offers: Fetch a new offer if the current one has expired
Image Formats
Offer images support multiple formats:
- Format: PNG, JPG, WebP
- Size: ≤ 300 KB recommended
- Encoding: Base64 with MIME prefix or direct URL
Base64 format:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
URL format:
https://cdn.toffee.com/logos/special-offer.png