Troubleshooting
Find the symptom you see, then work through its likely causes in order. Most checks need only your browser’s developer tools; Debug in the browser shows where to look.
Changes you make in the dashboard reach your site only after Grona rebuilds your workspace’s script and the CDN serves the new version. If a fix in the dashboard seems to have no effect, reload the page a little later before you look further.
Script not detected
Section titled “Script not detected”The installation check loads one page in a headless browser and looks for a <script> whose src ends with /workspaces/YOUR_WORKSPACE_ID/main.js, first in <head> and then in <body>. It covers only the URL you give it, so first check that you entered a page that carries the snippet.
If the snippet is on that page and the check still reports it missing, the usual causes are an optimisation plugin that changed the script URL, a consent tool or tag manager that adds the script late, or a page Grona cannot load. Verify your installation lists each one and its fix.
The check does not confirm that the anti-flicker script is present, that the tags are in the right order, or that the script ran.
Variation not showing
Section titled “Variation not showing”Open the page in a normal window and follow the quick check. Then work through these causes.
- Content Security Policy blocks the changes file. The runtime fetches each variation’s changes from
https://cdn.grona.ai, so that host must be inconnect-srcas well asscript-src. Without it, visitors see the original page and are not counted. See Content Security Policy. - The URL rules do not match this address. Exact URL rules must match query parameters other than UTM tags and click ids, paths are case-sensitive, and
httpdoes not matchhttps. See Target pages with URL rules. - A higher-priority campaign won the page. The first campaign that enrols the visitor wins, and lower-priority campaigns do not run. Check the priority order for the site. See Priority.
- The visitor is in the control group. In a test, some visitors see the original page by design. Use a preview link to see a specific variation.
- Audience rules or the schedule exclude the visitor. A signal with no value, such as an unknown location, never equals anything (only “is unknown” and conditions under not match it). Schedules use UTC and the visitor’s clock. See Target audiences.
- The workspace waits for consent. Visitors who have not consented see the original page for tests, and nothing is counted. See Consent and storage.
- An ad or content blocker blocks Grona. If
cdn.grona.aiis blocked, the scripts do not load and the original page shows. Grona does not offer first-party serving. - The element has changed. A change finds its element by the page structure. If your site’s layout or content changed since the variation was built, the change can miss its element and do nothing. Edit the variation again against the current page.
- A text change on a React or Vue element was skipped. To avoid breaking your app, the runtime skips text changes on elements whose children React or Vue control. See Single-page applications.
Page blank for a few seconds
Section titled “Page blank for a few seconds”The anti-flicker script hides the page body on every page that has the snippet, until main.js has loaded and applied any changes. A safety timer reveals the page at most 5 seconds after the anti-flicker script runs. A long blank means main.js is slow or not running.
main.jsis blocked by a blocker, a Content Security Policy or a network filter, whileantiflicker.jsstill runs. The page then stays hidden until the safety timer fires. Check the network panel for a failedmain.jsrequest.- An optimisation plugin delays
main.jsuntil the visitor interacts with the page. Exclude both Grona scripts from delaying. - The browser cannot run the runtime. Old browsers such as Internet Explorer 11 cannot run
main.jsat all, so the page can stay hidden until the timer fires. See Supported browsers. - A slow connection. The page stays hidden until
main.jshas downloaded. See Prevent flicker for the trade-off, and Performance.
Flicker
Section titled “Flicker”Visitors see the original content for a moment before the variation appears.
- The anti-flicker script is missing or asynchronous. It must be the synchronous second line of the snippet, with no
asyncordefer, at the top of<head>. Tag managers, optimisation plugins and framework script components that load it asynchronously cannot hide the first paint. See Prevent flicker. - The page was revealed by the safety timer. If
main.jsfinished after the timer, the changes still apply, but visibly. - It happens after an in-app navigation. On single-page applications there is no hiding on route changes, so the original can show briefly before the changes apply. See Single-page applications.
Different variation on www and the bare domain
Section titled “Different variation on www and the bare domain”The visitor id lives in the browser’s local storage, which is separate for each origin. https://www.shop.example.com and https://shop.example.com match the same campaigns, but they give the same visitor two different ids, and so possibly two different variations. The same applies to other subdomains and to http against https.
Redirect visitors to one host and one scheme. See Domains and subdomains.
Changes disappear after navigating in a single-page app
Section titled “Changes disappear after navigating in a single-page app”On a route change the runtime removes the current page’s changes and checks campaigns again for the new address.
- The new address does not match the campaign. That is expected: the changes are removed. Add a URL rule for the new route if it should show the variation too.
- Your app uses hash routing (
/#/basket). The fragment is ignored when matching, so hash routes cannot be targeted and do not trigger a new check. - You are using a preview link. Preview does not follow navigation. Open the preview link again on the new page.
Changes lost after the page re-renders
Section titled “Changes lost after the page re-renders”If your framework redraws an element after Grona changed it, the change is lost for that page view. The runtime retries changes whose element is not on the page yet for up to 20 seconds, but it does not re-apply changes that your app overwrites later on the same route.
- Target elements that your app renders once and does not redraw.
- For text in React or Vue components, change the copy in your app rather than in a Grona variation.
See Single-page applications and Server rendering and hydration.
Nothing runs until consent
Section titled “Nothing runs until consent”There are two different causes.
- Your consent tool blocks the Grona tags. Nothing loads, no page is hidden and no campaign runs until the visitor accepts. The installation check reports the script as absent. Decide whether Grona should load before consent, and configure your consent tool accordingly.
- The workspace is set to wait for consent. The script loads, but until it finds consent it stores and sends nothing, and visitors see the original page for tests. Grona reads Google Consent Mode
updateentries, OneTrust, Cookiebot and Shopify’s customer privacy setting. With any other consent tool, visitors always count as not consented unless your tool also sends a Google Consent Mode update. Consent given during a page view counts from the next page view.
See Consent and storage and Consent platforms.
CSP errors in the console
Section titled “CSP errors in the console”A Content Security Policy error that names cdn.grona.ai or api.grona.ai means your policy is missing one of Grona’s directives. The most common miss is https://cdn.grona.ai in connect-src: the scripts load, but the variation’s changes file is blocked. An error about an inline style names no host; it means style-src needs 'unsafe-inline' for the anti-flicker style and the styles variations add. A variation that inserts a block with its own script also needs 'unsafe-inline' in script-src, and sites that enforce Trusted Types cannot use inserted blocks. Content Security Policy lists every directive and gives a policy you can copy.
Lighthouse shows no change
Section titled “Lighthouse shows no change”Grona treats Lighthouse, PageSpeed Insights, GTmetrix, Pingdom and headless Chrome as bots. They get the original page: no hiding, no campaign and no variation. So these tools show neither the variation nor the effect of the anti-flicker script. Use a normal browser to see the variation, and real-visitor data to measure page speed. See Performance.
Conversions not counted
Section titled “Conversions not counted”- The page was a preview. Preview links record nothing.
- The visitor has not consented in a workspace that waits for consent.
- The call was queued through an older stub that drops the event name. Use the stub in the JavaScript API reference.
- The request to
api.grona.aiis blocked by a Content Security Policy or an ad blocker. - The event name does not match the goal in the dashboard.
- The order code was already counted. A goal counts once per
order_id,order_code,order_numberorbooking_id.
See Track conversions and custom events.
Preview link shows the original page
Section titled “Preview link shows the original page”- The
gronaPreviewparameter was lost. A redirect that drops the query string, or a click to another page, removes it. Check that the address still containsgronaPreview=. - The page does not load the Grona script. Preview needs the snippet on the page you open.
- A Content Security Policy blocks
api.grona.ai. Preview fetches the variation from the API, so it needsconnect-src https://api.grona.ai. - The variation id is wrong, or the variation has no changes yet. A control variation, or a variation you have not edited, shows the original page.
- The changes miss their elements. If the page differs from the one the variation was built on, a change can miss its element. Edit the variation against the current page.