Skip to content
The mobile SDKs are available on request. Email support@grona.ai to get access.

Identify shoppers

This page connects Grona to your sign-in flow. Identify the shopper when they sign in or when your app restores a session, pass their profile so audience rules can read it, and clear both at logout. Shoppers who are not identified still see campaigns that target installs, but never campaigns that target customers, such as every offer.

  1. Call Grona.identify with your internal customer id as soon as you know it: after sign-in, and at launch when your app restores a saved session.

    import ai.grona.sdk.Grona
    fun onSignedIn(session: AcmeSession) {
    Grona.identify(session.customerId) // "cus_7Hq2Lm9x"
    }
  2. Call Grona.setProfile with data from your own authenticated session. Bind the profile to the same customer id.

    import ai.grona.sdk.Grona
    import ai.grona.sdk.GronaProfile
    val profile = GronaProfile.Builder("cus_7Hq2Lm9x")
    .segment("returning_buyer")
    .list("usual_items", listOf("sku_10432", "sku_20877"))
    .attribute("store_format", "express")
    .build()
    Grona.setProfile(profile)
  3. At logout, call Grona.identify(null) or Grona.reset(). See Log out.

Both calls are safe from any thread. Call identify before setProfile, because a profile for any other customer is ignored.

  • Opaque and internal. Pass the id your systems use for the customer, such as cus_7Hq2Lm9x. Never pass an email address, a phone number or a national id.
  • Format. The id must match [A-Za-z0-9._:-]{1,128}. Any other value is ignored and the SDK logs a warning.
  • All-digit ids. The SDK cannot tell an opaque number from a phone number. It accepts an all-digit id of 9 or more characters but logs a warning. Do not pass one.
  • Stable. Use the same id on every device and on your backend. Customer-unit campaigns assign arms from it, and your grant backend checks grants against it.

Passing the id that is already identified does nothing. Passing a different id clears the profile and any grants, then starts a new grant fetch if you set a grant source.

A profile carries per-shopper data that audience rules read through the profile.* fields. It comes only from your app, from your own authenticated session. Grona never serves profiles itself.

Builder method Rule field What it holds
GronaProfile.Builder(customerId) The customer the profile belongs to. It must equal the id passed to identify.
segment(id), segments(ids) profile.segments Opaque segment ids, such as returning_buyer.
list(name, productIds) profile.lists.<name> A named list of product ids, such as the shopper’s usual items. Decisions can draw products from it.
attribute(name, value) profile.attributes.<name> A string attribute, such as a store format.

Until a matching profile is set, every rule that reads profile.* is unknown, and a campaign whose audience is unknown stays inactive. So a profile-targeted campaign never shows to a shopper who is not identified, not even through a not rule. When the profile arrives, live placements re-evaluate. The debug view shows audience: profile unknown for campaigns waiting on one.

Call Grona.setProfile(null) to clear the profile while the shopper stays identified.

Two calls end a signed-in session. They clear different amounts.

Call Clears Keeps
Grona.identify(null) Customer id, profile, grants Install id, event queue, basket snapshot, preview pins
Grona.reset() Customer id, profile, grants, event queue, basket snapshot, preview pins and session, and issues a new install id Configuration state

Use reset() for erasure requests and wherever the next shopper on the device must not inherit this install’s history. A new install id assigns install-unit campaigns afresh, so the device may move between arms. After reset(), push the basket again if the cart is not empty.