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

Consent

This page connects your consent flow to Grona. The SDK starts in .unknown, where it sends no events, and it does not remember consent between launches. You pass the shopper’s answer with Grona.setConsent on every launch and whenever it changes. Campaigns render in every state: consent controls what the SDK stores and sends, not what the shopper sees.

  1. At launch, right after Grona.start, pass the answer your app stored:

    import Grona
    func applyStoredConsent(_ answer: AcmeConsentAnswer) {
    switch answer {
    case .accepted:
    Grona.setConsent(.granted)
    case .declined:
    Grona.setConsent(.denied)
    case .notAsked:
    Grona.setConsent(.unknown)
    }
    }
  2. Call setConsent again whenever the shopper changes their answer, for example from your privacy settings screen.

setConsent is safe from any thread. Your app owns the consent prompt and stores the answer; the SDK starts in .unknown on every launch until you call it. Which purpose in your consent text covers Grona is your decision and your counsel’s.

GronaConsent Events Stored on the device
.unknown (default) Kept in memory only, at most 500, oldest dropped. Nothing is sent. No events.
.granted Stored and sent. Events buffered before consent are dropped, unless sendPreConsentEvents is on. The event queue, at most 1,000 events or 7 days.
.denied Buffer dropped, nothing collected. The event queue and preview pins are deleted.

Under every state:

  • Campaigns still render. Evaluation happens on the device.
  • The configuration fetch carries no identifiers.
  • The install id and the configuration state stay on the device. Under .denied nothing sends them. Deleting them would move shoppers between arms and weaken the configuration’s rollback protection.

Under .denied the SDK also refuses preview pairing, because the pairing request carries the install id.

Events from before the shopper answered are kept in memory. By default they are dropped when consent is granted, so only events after the answer are sent.

let options = try GronaOptions(
workspaceKey: "acme-market",
configKeys: ["acme-market-2026-10": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE..."],
sendPreConsentEvents: true
)

With sendPreConsentEvents: true, the SDK sends the buffered events once consent is granted. The option is off by default.

The SDK keeps its files in one folder inside your app’s container, Library/Application Support/ai.grona.sdk/:

  • the install id;
  • the configuration state: the cached signed configuration, its ETag and the record of the highest configuration version accepted;
  • the event queue, only once consent is granted;
  • preview pins.

The folder is marked as excluded from backups. Its files use the completeUntilFirstUserAuthentication data protection class, so iOS keeps them encrypted and unreadable after a restart until the shopper first enters their passcode. The customer id, the profile, grants and the basket snapshot live in memory only, so identify the shopper and push the profile and basket again after every launch. The SDK does not use the keychain or UserDefaults, so deleting your app deletes everything the SDK stored, and a reinstall starts with a new install id.

Grona.reset() clears the event queue, the customer id, the profile, grants, the basket snapshot, preview pins and the session, and issues a new install id. Call it for an erasure request on the device. For data already sent, see App Store privacy and privacy manifest.