Placements
Placements are in-app surfaces your team creates in GameStudio and targets to screens and segments: stories, banners, nudges, the dynamic island, surveys, tooltips, coachmarks. They need no app release. Each one renders from the rewards UI build, so a new look also arrives over the air.
Types
| Model | Types | Host code |
|---|---|---|
| Overlay | modal, sheet, fullscreen, banner, toast, island, pip, survey, game, floating | None |
| Inline | stories, carousel, widget, checklist | A slot, or a slot_target on Android Views |
| Anchored | tooltip, spotlight, coachmark, badge | An id on the view |
| Screen | inbox | openInbox() |
Only one overlay shows at a time, in priority order. Inline slots render independently.
Inline slots
Put a slot where a section may appear. It takes no space until a placement targets it.
- Android
- iOS
<com.theflyy.sdk.FlyyPlacementView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flyySlot="home_stories" />
FlyySlot("home_stories")
FlyyStories(slot = "home_stories") // stories only
Without a slot (Views): a placement with a slot_target inserts itself
before, after, or inside a view you already have, found by its android:id,
tag or content description. The parent must be a vertical LinearLayout.
let slot = FlyyPlacementView(slot: "home_stories") // UIKit
stackView.addArrangedSubview(slot)
FlyySlot("home_stories")
FlyyStories(slot: "home_stories")
Targets: "next to an element"
Compose and SwiftUI layouts can't be inserted into, so wrap a section once and GameStudio can place content before, after, at the top or at the bottom of it:
- Android
- iOS
FlyyTarget("home_rewards_promo") { RewardsPromoCard() }
RewardsPromoCard().flyyTarget("home_rewards_promo")
Anchors
Tooltips, spotlights, coachmarks and badges point at a view.
- Android
- iOS
Flyy.registerAnchor("buy_btn", buyButton)
Flyy.unregisterAnchor("buy_btn")
// Compose: a testTag is already an anchor — no other code
Button(onClick = {}, modifier = Modifier.testTag("buy_btn")) { Text("Buy") }
Views with an android:id or a tag are found automatically, too.
Flyy.registerAnchor("buy_btn", view: buyButton)
// SwiftUI
Button("Buy") { }.flyyAnchor("buy_btn")
Every slot, target and anchor is reported to GameStudio, along with ids the SDK
finds on its own (View ids, tags, Compose testTags). The editor shows them as a
picker.
Manual triggers
Useful for QA:
Flyy.showPlacement("diwali_story")
Flyy.showNudge("cart_nudge")
Flyy.showDynamicIsland("order_live")
Flyy.dismissPlacements()
How config stays current
The SDK re-fetches placement config:
- at init, and after
setUser/ login (lists are per segment), - on every app foreground, at most once a minute,
- immediately on a
config_refreshpush sent when GameStudio publishes (see Push), - when you call
Flyy.refreshFloatingWidgets().
A change applies at once: new overlays show, slots re-render, and a deleted placement disappears.
Events
Placements report placement_shown, placement_clicked, placement_dismissed,
placement_completed, placement_answered and story_viewed, each with
placement_id and type. Frequency caps count placement_shown.