Rendering modes
Every Grona campaign on mobile renders in one of two modes: the SDK draws a native component in a slot view, or your app draws its own UI from a decision. This page explains both, compares them, and shows how both are measured. Read it before you add your first placement, because the choice decides which call you wire up.
SDK-rendered components
Section titled “SDK-rendered components”You place a slot view in your layout and give it a placement and the current screen. When a campaign wins that placement, the SDK draws one of four native components inside the slot: a banner, a progress bar, an offer or a message. The content (copy, images, colours, the call to action) comes from the signed configuration, so you can change it without an app release.
The SDK styles components with theme tokens you pass at initialisation (fonts, colours and corner radius), and a campaign can override colours. Prices, totals and product names in the copy come from your app’s own product data, never from the configuration. When the shopper taps a call to action, the SDK validates the action and calls your app to add products or open a route.
See Grona components for what each component shows.
Host-rendered decisions
Section titled “Host-rendered decisions”You call the decision call for a placement, passing the view the content will occupy (the anchor) and the current screen. The SDK delivers a decision, or null when there is nothing to show. Your app then draws the result with its own views: your product cells, your prices, your stock badges and your add buttons.
A decision is one of four types:
| Type | Use |
|---|---|
rail |
A horizontal list of products, such as frequently bought together |
bundle |
A set of products added together |
product_card |
A single product |
substitute |
A replacement for an out-of-stock basket line, on cart_line only |
A decision carries a title, subtitle, badge and call-to-action label (all optional), the list of products, and extras, a flat map of short layout hints such as a position in a feed. Products your app does not know, or has out of stock, are dropped before delivery, and a decision left with no products is not delivered. When the shopper taps your button, you call the decision’s add, add-all or replace action. The SDK validates the products and quantities, calls your app’s add or replace, and records the action event with the result. Treat any decision type your app does not recognise as no decision, because newer configurations can add types.
See Patterns for host-rendered decisions for how to render them without layout jumps.
Compare the modes
Section titled “Compare the modes”| SDK-rendered components | Host-rendered decisions | |
|---|---|---|
| What renders | Banner, progress, offer, message | Your own product views |
| Visual control | Theme tokens and per-campaign colours | Complete: it is your UI |
| New look without a release | Yes, within the four components | Only within what your layout already supports, steered by extras |
| Products, prices, stock | From your app’s product lookup | From your app’s own views and data |
| Offers with a reward | Yes, the offer component (with a grant) |
No |
| Actions | Add, add several, navigate, from the component’s button | Add, add all, replace, dismiss, from your own tap handlers |
| Exposure reporting | Automatic | Automatic, measured on the anchor you pass |
| Work in the app | Add a slot view | Add an anchor and draw the decision |
Choose SDK-rendered components when the content is a message, a promotion or a progress nudge that does not need your product cells. Choose host-rendered decisions when the content is products, so they look and behave exactly like the rest of your catalogue. Each campaign uses one mode. A slot view only considers component campaigns for its placement, and the decision call only considers decision campaigns, so wire the call that matches the campaigns you plan for that placement.
Both modes are measured the same way
Section titled “Both modes are measured the same way”A fair test needs the control arm measured the same way as the treatment arm, even though control shows nothing. So in both modes the SDK measures the same thing for every arm: the anchor. For SDK-rendered components, the anchor is the slot view itself. For host-rendered decisions, it is the view you pass to the decision call.
eligiblefires for every arm when a decision is computed for the placement.anchor_visiblefires for every arm once the anchor’s top edge has been inside the visible screen for one continuous second.servedandexposurefire for treatment only, when content is delivered and when half of it has been visible for a second.
An anchor with nothing to show stays visible at zero height. The slot view does this for you. With host-rendered decisions you must do it yourself.
See Events and exposure for the full event list.
Next steps
Section titled “Next steps”- Placements
- Android: Render Grona components and Host-rendered decisions
- iOS: Render Grona components and Host-rendered decisions