Use case · Web · iOS · Android

One UI change, every platform at once

Show a module, hide it, reorder the page, reword the button — on web, iOS and Android together. Not three separate experiments running in three different weeks, on three different release cycles.

frontend render = low riskno app release to change it

The problem

The app store sets the pace, so the mobile answer always arrives late.

Web ships the change on Tuesday. iOS ships it a fortnight later, after review. Android lands somewhere in between, and a third of your users are still on a build from March. By the time all three are live, the market has moved and the numbers are not comparable.

So mobile gets tested less. Teams fall back on shipping the same change to everyone and watching the aggregate — which is not an experiment, it is a hope. Or they hardcode a remote flag per platform, and end up with three flags that drift out of sync.

The worst version is a user who sees the new layout on the website and the old one in the app. Same person, same account, two different products.

three codebases, three timelines
// web — shipped Tue
if (flags.newLayout) { ... }

// ios — in review, ~10 days
if remoteConfig.newLayoutV2 { ... }

// android — shipped, but 31% of
// installs are on an older build
if (config.getBool("new_layout")) { ... }

// after — one parameter, one policy,
// same user gets the same variant
// everywhere, changed without a release

What you put under control

Visibility, order, and copy are values. Declared once per platform.

Parameters
ParameterTypeControls
pdp.module_orderjsonsection sequence
pdp.reviews_visiblebooleanshow / hide
pdp.cta_labelstringmessaging
pdp.sticky_ctabooleanshow / hide
Surfaces that consume them
SurfaceKindRole
Web product pagefrontendrender
iOS product screenfrontendrender
Android product screenfrontendrender

Risk class: low

Every binding is a render — nothing here decides a price or writes to a system of record. With a certified plan and no open risks, this is the one case that can start without waiting on an approval.

Variants are parameter value sets
Variantmodule_orderreviews_visiblecta_label
controlgallery, specs, reviewstrue"Add to cart"
social-firstgallery, reviews, specstrue"Add to cart"
minimalgallery, specsfalse"Buy now"

Reordering, hiding and rewording move together as one coherent variant — which is how you find out whether the layout or the copy did the work.

Per-platform, when you need it
Same variant, all platforms
The default. One consistent experience per user.
recommended
Scope a policy to one surface
Ship the sticky CTA on mobile only, where it matters.
supported

The same user sees the same thing

Assignment is deterministic from the user key, so platforms cannot disagree.

Each SDK computes the assignment locally from the same user key and the same rules, so no coordination is needed between platforms and nothing has to be stored. A customer who browses on the website at lunchtime and opens the app in the evening is in the same arm both times.

That is what makes the result trustworthy. If web and mobile assigned independently, a user could be in the treatment on one and the control on the other, and every cross-device journey would quietly contaminate the measurement.

  • One conformance spec — every SDK is tested against the same shared fixtures.
  • No release required — changing the value changes all three at once.
  • Old builds are safe — an install that never fetches config still renders your compiled default.
pdp.module_order social-first
Web
React
iOS
Swift
Android
Kotlin
One user key · one arm · resolved locally on each platform

How it runs

Low risk, so the safe path is also the fast path.

Canary → Experiment → Rollout
Auto-approved: low risk, certified plan, no open risks.

Because the change is low risk and its plan resolved cleanly from a certified protocol, traffic starts without a person in the loop. Promotion to the product default still needs an approval — that part never changes.

Mobile gets one guardrail the web does not: crash-free rate. A layout parameter that puts an unexpected value into an older build should stop itself, not wait for a one-star review.

Phases live
Setup
Canary
Experiment
Rollout
Complete
Guardrails on every phase
crash_free_rate
must not decrease > 0.1% · iOS and Android
blocking
render_error_rate
must not increase > 0.5%
blocking
add_to_cart_rate
must not decrease > 2%
warning

What you get back

One verdict for the change, and a per-platform breakdown underneath it.

pdp-layout-social-first / measurement live
Social-first wins — ramping
Effect holds on all three platforms. Crash-free rate unchanged. Promotion to default awaiting approval.
primary metric
+3.4%
add_to_cart_rate · per product view
platforms agreeing
3 / 3
direction consistent, magnitude varies
guardrails
3 / 3
passing, including crash-free rate
Web breakdown
reviews above specs · strongest effect
+4.1%
iOS breakdown
same direction, smaller magnitude
+2.8%
Android breakdown
same direction, smaller magnitude
+2.4%
minimal variant rejected
hiding reviews cost conversion on every platform
−5.2%

A per-platform breakdown is the thing you cannot get from three separate experiments run in three different weeks. Here the direction is consistent and the magnitude differs — which is a real finding about mobile, not an artefact of timing.

The rejected variant matters just as much. "Hiding reviews to shorten the page" is a recurring suggestion, and now it has a number attached to it that anyone can find.

Retained after this change

Reviews above specs lifted add-to-cart on all three platforms, strongest on web. Hiding reviews entirely cost 5.2% — do not retry without a different hypothesis.

Searchable by parameter, surface, or metric

Keep reading

The mechanics behind this page.

Stop waiting on app review to learn something

Parameterize one module's visibility. The next layout question gets answered in days, on every platform.