Data, privacy and security
This page summarises what the Grona website script and mobile SDKs store and send, how consent changes that, and how the data is protected in transit. It is written for the engineers, security reviewers and privacy teams who sign off an integration. The detailed consent pages for each surface are linked in each section.
Website script
Section titled “Website script”What it stores
Section titled “What it stores”The script writes no cookies. It stores its data in first-party Web Storage (localStorage and sessionStorage) on your own origin, and sets no third-party storage. It reads cookies only to detect consent from supported consent tools, and to read Shopify’s market cookie when a campaign targets by market.
| Key | Storage | Purpose | Lifetime |
|---|---|---|---|
grona_client_data |
localStorage |
A random visitor id, used to keep a visitor in the same variation and to tie page views to conversions | 1 year, then a new id |
grona_session_id, grona_session_start, grona_last_activity |
sessionStorage |
The current visit | The tab’s life; a new visit starts after 30 minutes without activity or 7 hours in total |
grona_recent_pageviews |
sessionStorage |
Recent page-view ids, so a quick reload is not counted twice | 90 seconds per entry |
Some features add more keys, for example a consent note on workspaces that wait for consent, or a short visit history for audience rules that use earlier visits. Consent and storage has the full table.
What it sends
Section titled “What it sends”The script sends the data it collects only to api.grona.ai. It downloads its own files from cdn.grona.ai, and a variation that inserts a block can load content from other origins (see Domains and network calls). It sends:
- Event batches. Page views, scroll depth, time on page, the end of a visit, clicks on elements Grona has tagged (with the first 100 characters of the clicked element’s text), campaign triggers and conversions. Each batch carries your workspace id, the random visitor and visit ids, the page URL, the referrer, the user agent, traffic-source fields and a coarse location.
- Location. Country, region and city come from headers on Grona’s own CDN response. No outside location service is called, and VPN or cloud traffic shows as unknown.
- Conversion data. Whatever you pass to
grona('track', eventName, data). Do not put personal data in it. - Anti-flicker timing reports.
main.jssends aloadedreport when it starts on each page view, with no visitor or visit id.antiflicker.jssends atimeoutreport if its 5-second timer has to reveal the page; it includes the visitor and visit ids only whenmain.jshas already set them. Both carry your workspace id, the page URL, the user agent and a duration, and neither is sent for bots. See Prevent flicker.
Page views are sent only after a campaign enrols the visitor. The exception is measuring every page, which the workspace owner or an admin can switch on for a limited time (7 days by default): the script then counts one page view on every page that no campaign takes, and changes nothing.
Consent
Section titled “Consent”Each workspace has a consent mode, set in the Grona dashboard under Settings > Privacy and consent by answering “Must visitors consent before Grona stores anything?”. “Yes, wait for consent” gives Wait for consent, and “No, consent isn’t needed” gives Not required. A workspace that has not answered does not wait for consent.
With Wait for consent, the script stores nothing and sends no events until a supported consent tool reports analytics consent. Until then the visitor sees the original page, except for audience groups shown to everyone that need no stored data, such as device, location, time or language. The supported sources are Google Consent Mode update entries, OneTrust, Cookiebot and Shopify’s customer privacy API. Other consent tools are not read: on a Wait for consent workspace, their sites always show the original page unless the tool also sends a Google Consent Mode update. Consent given on a page counts from the next page view.
One request is sent regardless of consent: the anti-flicker timeout report, if the 5-second timer has to reveal the page. Before consent under Wait for consent it carries no visitor or visit id. The loaded report is sent only with consent in this mode.
Read Consent and storage and Consent platforms before you choose a setting.
Mobile SDKs
Section titled “Mobile SDKs”The SDKs are designed to keep shopper data on the device. Targeting and assignment run locally against a signed configuration, and the configuration download carries no identifiers.
What the SDK collects
Section titled “What the SDK collects”- An install id. A random UUID the SDK creates and owns. It lives in app-private storage that the SDK excludes from backups: on Android that also covers device transfer, and iOS treats backup exclusion as a hint. The Android SDK never reads the advertising ID, OAID,
ANDROID_IDor App Set ID, and the iOS SDK never reads the advertising identifier (IDFA) or the identifier for vendor (IDFV). - A customer id, only if you pass one. It must be an opaque internal id, never a phone number, email address or national id.
- Campaign events. Which campaign, variant, arm and placement a shopper was assigned, when the anchor was visible, what was served and which actions were taken.
- Commerce events you forward. Product ids and prices are kept only for products Grona campaigns showed or added in the current session. For any other product, the event is counted without the id or price. A purchase carries the order id, the total, the treatments and only those session products. The full basket, browsing history and search text never leave the device. Exception: on keyed placements such as
cart_line, campaign events carry the line’s product id as theirkey, in every arm. So while acart_linecampaign is live, the product ids of the cart lines bound to it leave the device.
Profiles and baskets you pass to the SDK are used for on-device decisions. Events never include the profile or the full basket. While a cart_line campaign is live, campaign events do carry the product ids of the cart lines bound to it, as the exception above describes.
Consent
Section titled “Consent”| Consent | What happens |
|---|---|
UNKNOWN (default) |
Events are kept in memory only, up to 500. Nothing is written to disk and nothing is sent. |
GRANTED |
Events are stored and sent. Events from before consent are dropped unless you turn on sending them. |
DENIED |
Nothing is collected. The event queue and preview pins are deleted. Content still renders, because decisions stay on the device. |
On the device, the event queue holds at most 1,000 events or 7 days, whichever comes first. Grona.reset() clears the queue, the customer id, profile, grants, basket snapshot and preview pins, and creates a new install id; call it on logout or when a shopper asks to be erased.
See Consent and data minimisation, and the store disclosures in Google Play Data safety and App Store privacy and privacy manifest.
Transport and integrity
Section titled “Transport and integrity”- Website. The scripts, variation files and every request are served over HTTPS from
cdn.grona.aiandapi.grona.ai. - Mobile. The SDK uses HTTPS only and refuses
http://URLs even when your app allows cleartext traffic. It does not pin certificates. Integrity comes from signatures instead: the configuration, preview pins and grants are signed by Grona with ES256 and verified on the device against the public keys you pass. A configuration with a bad signature, for another workspace, older than one already accepted or past its expiry is rejected, and the SDK keeps the last good one. - Money offers. An offer is display state until your order backend verifies its Grona-signed grant. Single use is enforced on the grant’s id, and the applied value comes only from the verified claims. See Grants and order verification.
- Secrets. The secret API key is server side only, and Grona stores it as a one-way hash. The SDK logger is silent by default and never logs customer ids, basket contents, tokens or keys. See Keys and environments.
Roles and responsibilities
Section titled “Roles and responsibilities”Grona’s privacy policy names Grona Ltd as the data controller for the personal data it collects through its own website and service, such as your team’s account details. The privacy policy and terms of service do not set out Grona’s role for the visitor and shopper data that the script and SDKs collect on your website and in your apps. If your review needs those terms in writing, for example a data processing agreement, contact support@grona.ai.
Your side of the integration decides a lot of what is collected:
- You choose the website consent setting, and you pass consent to the SDK from your own consent flow.
- You choose what goes into
grona('track', ...)calls and into the SDK’s customer id and profile. Keep them free of names, emails, phone numbers and national ids. - You verify grants on your order backend before you apply an offer.
This page does not list certifications, server-side retention periods or sub-processors. Ask support@grona.ai if your review needs them.
Report a security issue
Section titled “Report a security issue”Send security reports to support@grona.ai. Include the affected host, page or SDK version, the steps to reproduce, and what an attacker could do. Do not include secret keys or real customer data. See Get help.