import React, { useEffect, useState } from 'react'; import { FaCircleInfo } from 'react-icons/fa6'; import { FiChevronDown, FiChevronUp } from 'react-icons/fi'; /** * localStorage key driving the "How to read this report" open/closed * state. Default behavior on first load is open; if the merchant * collapses the callout we persist that choice so the page renders * the way they last left it on subsequent visits. */ const HOW_TO_READ_HIDDEN_KEY = 'recomaze.visibility.howToReadHidden'; interface HowToReadReportProps { /** Brand display name shown explicitly in the callout so merchants * immediately see "this report is about ". */ brandName: string; /** Brand domain - referenced in the body so the connection between * the brand row and the leaderboard rows is unambiguous. */ brandDomain?: string; } /** * "How to read this report" callout shown above the AI-visibility * report. Collapses into a one-liner on repeat visits, but the first * paragraph always names the merchant's brand explicitly so the * recurring "I don't see my brand anywhere, is this a bug?" support * thread doesn't happen. * * @param {HowToReadReportProps} props - Component props. * @returns {JSX.Element} Callout card. */ const HowToReadReport = ({ brandName, brandDomain, }: HowToReadReportProps): JSX.Element => { // Default to expanded; persist a "hidden" choice in localStorage so // subsequent loads honor it. Hydrate from storage inside an effect // (not initial state) to keep first paint deterministic. const [open, setOpen] = useState(true); const safeBrandName = brandName?.trim() || 'Your brand'; useEffect(() => { if (typeof window === 'undefined') return; try { const persistedHidden = window.localStorage.getItem( HOW_TO_READ_HIDDEN_KEY ); if (persistedHidden === '1') setOpen(false); } catch (_storageError) { // localStorage can throw in private mode / disabled storage - // fall back to the default-open state silently. } }, []); const toggleOpen = () => { setOpen(previousOpen => { const nextOpen = !previousOpen; try { if (typeof window !== 'undefined') { if (nextOpen) { window.localStorage.removeItem(HOW_TO_READ_HIDDEN_KEY); } else { window.localStorage.setItem(HOW_TO_READ_HIDDEN_KEY, '1'); } } } catch (_storageError) { // Ignore - toggle still works in-memory even if we can't // persist the choice. } return nextOpen; }); }; return (

How to read this report

{`Tracking ${safeBrandName}`} {brandDomain ? ` (${brandDomain})` : ''} {` against the brands AI assistants surface for your prompts.`}

{open && (

{`Each Monday we ask 16 prompts (products, scenarios, "best of", and geo) to multiple AI assistants and record what they say. The numbers below describe how often `} {safeBrandName} {` showed up in those answers and how that compares to the brands AI mentioned alongside you.`}

What the four KPI cards mean

Visibility score (0–100): blended health metric. Share of voice: % of all brand mentions that pointed to {safeBrandName}. Rank #N of M: where {safeBrandName} sits among every brand AI surfaced. Sentiment: how AI described you when it did mention you.

Share of Voice

Share of Voice (SOV) ranks 20 brands, with their scores distributed as percentages totaling 100%. We display the top 5 brands, along with a few selected ones from outside the top 5 for context. The remaining brands are not shown because their SOV is negligible and wouldn{`'`}t add meaningful insight to the view.

Why your brand may not appear in the leaderboard

The Competitors leaderboard only lists rivals AI mentioned this week. We always pin a{' '} Your brand row at the top so {safeBrandName} is visible side-by-side even when share of voice is 0%. That means AI didn't mention you for any of the 16 prompts this week, and the “Problems detected” section explains why.

What to do next

Look at “Top losses” and “Problems detected”. Both list the prompts where AI ignored{' '} {safeBrandName}. Use the “Generate article” buttons on a loss to publish a piece of content engineered to win that prompt back next week.

)}
); }; export default HowToReadReport;