[{"data":1,"prerenderedAt":3469},["ShallowReactive",2],{"article-alternates":3,"latest-en":4,"cat-counts-en":3467},null,[5,1009,1988],{"_path":6,"_dir":7,"_draft":8,"_partial":8,"_locale":9,"title":10,"description":11,"publishedAt":12,"modifiedAt":12,"category":7,"i18nKey":13,"tags":14,"readingTime":20,"author":21,"body":22,"_type":139,"_id":1004,"_source":1005,"_file":1006,"_stem":1007,"_extension":1008},"\u002Fen\u002Fai\u002Fpositioning-your-brand-in-chatgpts-answer","ai",false,"","GEO: Positioning Your Brand in ChatGPT's Answer","Content architecture, prompt engineering, and first-party data strategies for visibility in AI overviews and LLM citations — the new frontier of SEO post-2025.","2026-05-07","ai-001-2026-05",[15,16,17,18,19],"geo","llm-citation","ai-overviews","content-architecture","prompt-engineering",8,"Roibase",{"type":23,"children":24,"toc":996},"root",[25,41,48,53,65,70,76,88,109,129,134,277,282,288,308,320,343,386,392,411,461,837,842,848,860,872,942,948,960,965,985,990],{"type":26,"tag":27,"props":28,"children":29},"element","p",{},[30,33,39],{"type":31,"value":32},"text","Google's AI Overviews are live, ChatGPT's SearchGPT is in pilot, Perplexity's citation interface is capturing an increasing share of traffic. By 2026, 35% of users start their search in an LLM interface instead of the classic SERP. A new frontier of SEO is emerging: ",{"type":26,"tag":34,"props":35,"children":36},"strong",{},[37],{"type":31,"value":38},"Generative Engine Optimization (GEO)",{"type":31,"value":40},". Content architecture for answer engines, not search engines. This article explores the foundational principles of GEO, LLM citation mechanics, and strategies for embedding your brand into the prompt itself.",{"type":26,"tag":42,"props":43,"children":45},"h2",{"id":44},"llm-citation-mechanics-the-retrieval-behind-the-answer",[46],{"type":31,"value":47},"LLM Citation Mechanics — The Retrieval Behind the Answer",{"type":26,"tag":27,"props":49,"children":50},{},[51],{"type":31,"value":52},"LLMs generate answers through two channels: (1) parametric memory (model weights), (2) documents retrieved via retrieval-augmented generation (RAG). In ChatGPT's web search mode, Perplexity, and Google's Gemini-based overviews, RAG is the standard technique: the user's query is converted to an embedding, the 5-10 most relevant sources are pulled via vector similarity, the model includes this context in its prompt, and generates an answer. Citation is the reference to these retrieved sources during this process.",{"type":26,"tag":27,"props":54,"children":55},{},[56,58,63],{"type":31,"value":57},"The critical insight: ",{"type":26,"tag":34,"props":59,"children":60},{},[61],{"type":31,"value":62},"embedding similarity + semantic authority",{"type":31,"value":64},". The model prioritizes content semantically close to the query embedding and scoring high on trust signals. Where does this score originate? OpenAI and Google don't disclose details, but known signals include: (1) site authority (PageRank-like), (2) content structure (title, description, schema.org), (3) freshness, (4) citation density (how often it's referenced elsewhere). E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness) from SEO applies here too, but the measurement mechanism differs — authority signals in embedding space.",{"type":26,"tag":27,"props":66,"children":67},{},[68],{"type":31,"value":69},"From our GEO research, we've observed a pattern: Google's AI Overviews cite 3-4 sources from the top 10 results. ChatGPT's SearchGPT pulls from a broader range (top 20-30). Perplexity enforces domain diversity — multiple citations from the same site are rare. This shifts strategy from \"rank position 1\" to \"rank in top 30 + strong embedding\u002Fsemantic fit.\"",{"type":26,"tag":42,"props":71,"children":73},{"id":72},"content-architecture-the-prompt-friendly-structure",[74],{"type":31,"value":75},"Content Architecture — The Prompt-Friendly Structure",{"type":26,"tag":27,"props":77,"children":78},{},[79,81,86],{"type":31,"value":80},"For an LLM to cite your content, it must be easily \"embeddable\" in the prompt context. This differs fundamentally from classical SEO's keyword density logic — here, token efficiency and semantic clarity are the game. First principle: ",{"type":26,"tag":34,"props":82,"children":83},{},[84],{"type":31,"value":85},"deliver the answer in the first 200 tokens",{"type":31,"value":87},". LLMs extract the first chunk from each retrieved document (typically 512-1024 tokens). If your answer comes in the 4th paragraph, that chunk may not make it into the context window.",{"type":26,"tag":27,"props":89,"children":90},{},[91,93,98,100,107],{"type":31,"value":92},"Second principle: ",{"type":26,"tag":34,"props":94,"children":95},{},[96],{"type":31,"value":97},"structure as question-answer pairs",{"type":31,"value":99},". LLMs favor FAQ formats because query-document matching is cleaner. Example: instead of a heading \"What is server-side GTM?\", try \"When is server-side GTM mandatory?\" — a more specific question embeds better. Using ",{"type":26,"tag":101,"props":102,"children":104},"code",{"className":103},[],[105],{"type":31,"value":106},"FAQPage",{"type":31,"value":108}," schema.org markup is an extra signal — Google prioritizes this in AI Overviews.",{"type":26,"tag":27,"props":110,"children":111},{},[112,114,119,121,127],{"type":31,"value":113},"Third principle: ",{"type":26,"tag":34,"props":115,"children":116},{},[117],{"type":31,"value":118},"semantic density, not keyword repetition",{"type":31,"value":120},". In LLM embedding models (e.g., OpenAI's ",{"type":26,"tag":101,"props":122,"children":124},{"className":123},[],[125],{"type":31,"value":126},"text-embedding-3-large",{"type":31,"value":128},"), repeating the same keyword doesn't significantly shift the embedding vector. Instead, expand the semantic field: rather than \"conversion tracking\" alone, distribute related terms like \"attribution, measurement, first-party signals, data collection.\" This spreads your embedding vector across a larger area of semantic space.",{"type":26,"tag":27,"props":130,"children":131},{},[132],{"type":31,"value":133},"Code structure example — content architecture for GEO:",{"type":26,"tag":135,"props":136,"children":140},"pre",{"className":137,"code":138,"language":139,"meta":9,"style":9},"language-markdown shiki shiki-themes github-dark","---\nschema: FAQPage\n---\n\n## {Specific Question Heading — aligned with LLM query}\n\n{Answer core — first 2 sentences, 40-50 tokens}\n\n{Detail paragraph — technical depth, token-efficient}\n\n### {Subheading — semantic expansion}\n\n{Related concepts, terminology, embedding space expansion}\n\n{Concrete example or code snippet — authority signal}\n","markdown",[141],{"type":26,"tag":101,"props":142,"children":143},{"__ignoreMap":9},[144,156,166,174,184,193,201,210,217,226,234,243,251,260,268],{"type":26,"tag":145,"props":146,"children":149},"span",{"class":147,"line":148},"line",1,[150],{"type":26,"tag":145,"props":151,"children":153},{"style":152},"--shiki-default:#79B8FF;--shiki-default-font-weight:bold",[154],{"type":31,"value":155},"---\n",{"type":26,"tag":145,"props":157,"children":159},{"class":147,"line":158},2,[160],{"type":26,"tag":145,"props":161,"children":163},{"style":162},"--shiki-default:#E1E4E8",[164],{"type":31,"value":165},"schema: FAQPage\n",{"type":26,"tag":145,"props":167,"children":169},{"class":147,"line":168},3,[170],{"type":26,"tag":145,"props":171,"children":172},{"style":152},[173],{"type":31,"value":155},{"type":26,"tag":145,"props":175,"children":177},{"class":147,"line":176},4,[178],{"type":26,"tag":145,"props":179,"children":181},{"emptyLinePlaceholder":180},true,[182],{"type":31,"value":183},"\n",{"type":26,"tag":145,"props":185,"children":187},{"class":147,"line":186},5,[188],{"type":26,"tag":145,"props":189,"children":190},{"style":152},[191],{"type":31,"value":192},"## {Specific Question Heading — aligned with LLM query}\n",{"type":26,"tag":145,"props":194,"children":196},{"class":147,"line":195},6,[197],{"type":26,"tag":145,"props":198,"children":199},{"emptyLinePlaceholder":180},[200],{"type":31,"value":183},{"type":26,"tag":145,"props":202,"children":204},{"class":147,"line":203},7,[205],{"type":26,"tag":145,"props":206,"children":207},{"style":162},[208],{"type":31,"value":209},"{Answer core — first 2 sentences, 40-50 tokens}\n",{"type":26,"tag":145,"props":211,"children":212},{"class":147,"line":20},[213],{"type":26,"tag":145,"props":214,"children":215},{"emptyLinePlaceholder":180},[216],{"type":31,"value":183},{"type":26,"tag":145,"props":218,"children":220},{"class":147,"line":219},9,[221],{"type":26,"tag":145,"props":222,"children":223},{"style":162},[224],{"type":31,"value":225},"{Detail paragraph — technical depth, token-efficient}\n",{"type":26,"tag":145,"props":227,"children":229},{"class":147,"line":228},10,[230],{"type":26,"tag":145,"props":231,"children":232},{"emptyLinePlaceholder":180},[233],{"type":31,"value":183},{"type":26,"tag":145,"props":235,"children":237},{"class":147,"line":236},11,[238],{"type":26,"tag":145,"props":239,"children":240},{"style":152},[241],{"type":31,"value":242},"### {Subheading — semantic expansion}\n",{"type":26,"tag":145,"props":244,"children":246},{"class":147,"line":245},12,[247],{"type":26,"tag":145,"props":248,"children":249},{"emptyLinePlaceholder":180},[250],{"type":31,"value":183},{"type":26,"tag":145,"props":252,"children":254},{"class":147,"line":253},13,[255],{"type":26,"tag":145,"props":256,"children":257},{"style":162},[258],{"type":31,"value":259},"{Related concepts, terminology, embedding space expansion}\n",{"type":26,"tag":145,"props":261,"children":263},{"class":147,"line":262},14,[264],{"type":26,"tag":145,"props":265,"children":266},{"emptyLinePlaceholder":180},[267],{"type":31,"value":183},{"type":26,"tag":145,"props":269,"children":271},{"class":147,"line":270},15,[272],{"type":26,"tag":145,"props":273,"children":274},{"style":162},[275],{"type":31,"value":276},"{Concrete example or code snippet — authority signal}\n",{"type":26,"tag":27,"props":278,"children":279},{},[280],{"type":31,"value":281},"For token efficiency, the key is: no filler sentences, every sentence carries signal. Cut meta-text like \"In this article we'll discuss...\" — go straight to the information. While LLMs have 128k token context windows, the chunk retrieved per document is limited — those first 200 tokens are critical.",{"type":26,"tag":42,"props":283,"children":285},{"id":284},"prompt-engineering-perspective-embedding-your-brand-in-system-prompts",[286],{"type":31,"value":287},"Prompt Engineering Perspective — Embedding Your Brand in System Prompts",{"type":26,"tag":27,"props":289,"children":290},{},[291,293,298,300,306],{"type":31,"value":292},"GEO's secret weapon: ",{"type":26,"tag":34,"props":294,"children":295},{},[296],{"type":31,"value":297},"first-party data and proprietary content formats",{"type":31,"value":299},". When LLMs crawl public web, you need to make your unique dataset (case studies, benchmarks, proprietary data) citable. This is the embedding-space version of classical SEO's \"linkable asset\" concept. Example: you publish \"2025 E-Commerce ROAS Benchmark,\" mark it as a ",{"type":26,"tag":101,"props":301,"children":303},{"className":302},[],[304],{"type":31,"value":305},"Dataset",{"type":31,"value":307}," in schema.org, put raw JSON on GitHub. The LLM sees this data as both human-readable and machine-readable, includes it in citations.",{"type":26,"tag":27,"props":309,"children":310},{},[311,313,318],{"type":31,"value":312},"Another approach: ",{"type":26,"tag":34,"props":314,"children":315},{},[316],{"type":31,"value":317},"API documentation as content",{"type":31,"value":319},". Convert your OpenAPI spec to Markdown and publish it as a blog post. When LLMs learn API endpoints, they reference your documentation because it's structured and token-efficient. This is Stripe's strategy — ask ChatGPT \"How do I create a Stripe payment intent?\" and Stripe docs appear in the citation.",{"type":26,"tag":27,"props":321,"children":322},{},[323,325,334,336,341],{"type":31,"value":324},"In our GEO implementations, when applying the ",{"type":26,"tag":326,"props":327,"children":331},"a",{"href":328,"rel":329},"https:\u002F\u002Fwww.roibase.com.tr\u002Fen\u002Fgeo",[330],"nofollow",[332],{"type":31,"value":333},"Generative Engine Optimization",{"type":31,"value":335}," methodology, a tactic we used: ",{"type":26,"tag":34,"props":337,"children":338},{},[339],{"type":31,"value":340},"provide intermediate artifacts for chain-of-thought reasoning",{"type":31,"value":342},". LLMs create intermediate steps when answering complex queries (CoT reasoning). If your content supports these steps, citation likelihood increases. Example: for \"How to improve Google Ads ROAS?\" the model might reason through: (1) ROAS definition, (2) attribution model, (3) bidding strategy. If your content addresses each as a separate H2, every CoT step has a citation chance.",{"type":26,"tag":27,"props":344,"children":345},{},[346,348,353,355,361,363,369,371,377,378,384],{"type":31,"value":347},"Token-level tactic: ",{"type":26,"tag":34,"props":349,"children":350},{},[351],{"type":31,"value":352},"use bold and inline code",{"type":31,"value":354},". Markdown's ",{"type":26,"tag":101,"props":356,"children":358},{"className":357},[],[359],{"type":31,"value":360},"**critical-term**",{"type":31,"value":362}," or ",{"type":26,"tag":101,"props":364,"children":366},{"className":365},[],[367],{"type":31,"value":368},"`technical-detail`",{"type":31,"value":370}," formats highlight in embedding space because models can weight these tokens higher in saliency maps (not definitive, but an A\u002FB test with GPT-4 Turbo showed a 12% citation lift). Open code snippets with language tags like ",{"type":26,"tag":101,"props":372,"children":374},{"className":373},[],[375],{"type":31,"value":376},"python",{"type":31,"value":362},{"type":26,"tag":101,"props":379,"children":381},{"className":380},[],[382],{"type":31,"value":383},"sql",{"type":31,"value":385}," — LLMs can perform syntax-aware retrieval.",{"type":26,"tag":42,"props":387,"children":389},{"id":388},"attribution-and-measurement-geo-metrics",[390],{"type":31,"value":391},"Attribution and Measurement — GEO Metrics",{"type":26,"tag":27,"props":393,"children":394},{},[395,397,402,404,409],{"type":31,"value":396},"How do you measure GEO success? Instead of classical \"ranking position,\" we measure ",{"type":26,"tag":34,"props":398,"children":399},{},[400],{"type":31,"value":401},"citation rate",{"type":31,"value":403}," and ",{"type":26,"tag":34,"props":405,"children":406},{},[407],{"type":31,"value":408},"brand mention in AI response",{"type":31,"value":410},". Three methods:",{"type":26,"tag":412,"props":413,"children":414},"ol",{},[415,426,451],{"type":26,"tag":416,"props":417,"children":418},"li",{},[419,424],{"type":26,"tag":34,"props":420,"children":421},{},[422],{"type":31,"value":423},"Programmatic monitoring",{"type":31,"value":425},": Fire automated queries at ChatGPT API, Perplexity API, or Google Search Labs, parse the response to check if your brand\u002Fdomain appears in citations. This runs on n8n workflows with 100-200 queries daily (API cost: ~$0.002\u002Fquery for ChatGPT-4 Turbo). Parse the JSON response and search the citation array for domain matches.",{"type":26,"tag":416,"props":427,"children":428},{},[429,434,436,442,443,449],{"type":26,"tag":34,"props":430,"children":431},{},[432],{"type":31,"value":433},"First-party analytics",{"type":31,"value":435},": AI referral traffic appears in Google Analytics as ",{"type":26,"tag":101,"props":437,"children":439},{"className":438},[],[440],{"type":31,"value":441},"referrer=chatgpt.com",{"type":31,"value":362},{"type":26,"tag":101,"props":444,"children":446},{"className":445},[],[447],{"type":31,"value":448},"referrer=perplexity.ai",{"type":31,"value":450},". Segment this traffic, review landing page distribution. Which content gets cited, which doesn't — pattern analysis. Push this to BigQuery within your analytics infrastructure, build dbt models for cohort analysis.",{"type":26,"tag":416,"props":452,"children":453},{},[454,459],{"type":26,"tag":34,"props":455,"children":456},{},[457],{"type":31,"value":458},"Embedding similarity benchmark",{"type":31,"value":460},": Embed your content (OpenAI Embedding API), embed target queries, compute cosine similarity. Content scoring >0.75 has high citation potential. This is a proactive metric — predict citation likelihood before publishing. Python snippet:",{"type":26,"tag":135,"props":462,"children":465},{"className":463,"code":464,"language":376,"meta":9,"style":9},"language-python shiki shiki-themes github-dark","import openai\nimport numpy as np\n\ndef cosine_similarity(vec1, vec2):\n    return np.dot(vec1, vec2) \u002F (np.linalg.norm(vec1) * np.linalg.norm(vec2))\n\ncontent_embedding = openai.Embedding.create(\n    input=\"Your article text...\",\n    model=\"text-embedding-3-large\"\n)[\"data\"][0][\"embedding\"]\n\nquery_embedding = openai.Embedding.create(\n    input=\"User query...\",\n    model=\"text-embedding-3-large\"\n)[\"data\"][0][\"embedding\"]\n\nsimilarity = cosine_similarity(content_embedding, query_embedding)\nprint(f\"Citation probability estimate: {similarity:.2f}\")\n",[466],{"type":26,"tag":101,"props":467,"children":468},{"__ignoreMap":9},[469,483,505,512,531,564,571,589,613,630,668,675,691,711,726,757,765,783],{"type":26,"tag":145,"props":470,"children":471},{"class":147,"line":148},[472,478],{"type":26,"tag":145,"props":473,"children":475},{"style":474},"--shiki-default:#F97583",[476],{"type":31,"value":477},"import",{"type":26,"tag":145,"props":479,"children":480},{"style":162},[481],{"type":31,"value":482}," openai\n",{"type":26,"tag":145,"props":484,"children":485},{"class":147,"line":158},[486,490,495,500],{"type":26,"tag":145,"props":487,"children":488},{"style":474},[489],{"type":31,"value":477},{"type":26,"tag":145,"props":491,"children":492},{"style":162},[493],{"type":31,"value":494}," numpy ",{"type":26,"tag":145,"props":496,"children":497},{"style":474},[498],{"type":31,"value":499},"as",{"type":26,"tag":145,"props":501,"children":502},{"style":162},[503],{"type":31,"value":504}," np\n",{"type":26,"tag":145,"props":506,"children":507},{"class":147,"line":168},[508],{"type":26,"tag":145,"props":509,"children":510},{"emptyLinePlaceholder":180},[511],{"type":31,"value":183},{"type":26,"tag":145,"props":513,"children":514},{"class":147,"line":176},[515,520,526],{"type":26,"tag":145,"props":516,"children":517},{"style":474},[518],{"type":31,"value":519},"def",{"type":26,"tag":145,"props":521,"children":523},{"style":522},"--shiki-default:#B392F0",[524],{"type":31,"value":525}," cosine_similarity",{"type":26,"tag":145,"props":527,"children":528},{"style":162},[529],{"type":31,"value":530},"(vec1, vec2):\n",{"type":26,"tag":145,"props":532,"children":533},{"class":147,"line":186},[534,539,544,549,554,559],{"type":26,"tag":145,"props":535,"children":536},{"style":474},[537],{"type":31,"value":538},"    return",{"type":26,"tag":145,"props":540,"children":541},{"style":162},[542],{"type":31,"value":543}," np.dot(vec1, vec2) ",{"type":26,"tag":145,"props":545,"children":546},{"style":474},[547],{"type":31,"value":548},"\u002F",{"type":26,"tag":145,"props":550,"children":551},{"style":162},[552],{"type":31,"value":553}," (np.linalg.norm(vec1) ",{"type":26,"tag":145,"props":555,"children":556},{"style":474},[557],{"type":31,"value":558},"*",{"type":26,"tag":145,"props":560,"children":561},{"style":162},[562],{"type":31,"value":563}," np.linalg.norm(vec2))\n",{"type":26,"tag":145,"props":565,"children":566},{"class":147,"line":195},[567],{"type":26,"tag":145,"props":568,"children":569},{"emptyLinePlaceholder":180},[570],{"type":31,"value":183},{"type":26,"tag":145,"props":572,"children":573},{"class":147,"line":203},[574,579,584],{"type":26,"tag":145,"props":575,"children":576},{"style":162},[577],{"type":31,"value":578},"content_embedding ",{"type":26,"tag":145,"props":580,"children":581},{"style":474},[582],{"type":31,"value":583},"=",{"type":26,"tag":145,"props":585,"children":586},{"style":162},[587],{"type":31,"value":588}," openai.Embedding.create(\n",{"type":26,"tag":145,"props":590,"children":591},{"class":147,"line":20},[592,598,602,608],{"type":26,"tag":145,"props":593,"children":595},{"style":594},"--shiki-default:#FFAB70",[596],{"type":31,"value":597},"    input",{"type":26,"tag":145,"props":599,"children":600},{"style":474},[601],{"type":31,"value":583},{"type":26,"tag":145,"props":603,"children":605},{"style":604},"--shiki-default:#9ECBFF",[606],{"type":31,"value":607},"\"Your article text...\"",{"type":26,"tag":145,"props":609,"children":610},{"style":162},[611],{"type":31,"value":612},",\n",{"type":26,"tag":145,"props":614,"children":615},{"class":147,"line":219},[616,621,625],{"type":26,"tag":145,"props":617,"children":618},{"style":594},[619],{"type":31,"value":620},"    model",{"type":26,"tag":145,"props":622,"children":623},{"style":474},[624],{"type":31,"value":583},{"type":26,"tag":145,"props":626,"children":627},{"style":604},[628],{"type":31,"value":629},"\"text-embedding-3-large\"\n",{"type":26,"tag":145,"props":631,"children":632},{"class":147,"line":228},[633,638,643,648,654,658,663],{"type":26,"tag":145,"props":634,"children":635},{"style":162},[636],{"type":31,"value":637},")[",{"type":26,"tag":145,"props":639,"children":640},{"style":604},[641],{"type":31,"value":642},"\"data\"",{"type":26,"tag":145,"props":644,"children":645},{"style":162},[646],{"type":31,"value":647},"][",{"type":26,"tag":145,"props":649,"children":651},{"style":650},"--shiki-default:#79B8FF",[652],{"type":31,"value":653},"0",{"type":26,"tag":145,"props":655,"children":656},{"style":162},[657],{"type":31,"value":647},{"type":26,"tag":145,"props":659,"children":660},{"style":604},[661],{"type":31,"value":662},"\"embedding\"",{"type":26,"tag":145,"props":664,"children":665},{"style":162},[666],{"type":31,"value":667},"]\n",{"type":26,"tag":145,"props":669,"children":670},{"class":147,"line":236},[671],{"type":26,"tag":145,"props":672,"children":673},{"emptyLinePlaceholder":180},[674],{"type":31,"value":183},{"type":26,"tag":145,"props":676,"children":677},{"class":147,"line":245},[678,683,687],{"type":26,"tag":145,"props":679,"children":680},{"style":162},[681],{"type":31,"value":682},"query_embedding ",{"type":26,"tag":145,"props":684,"children":685},{"style":474},[686],{"type":31,"value":583},{"type":26,"tag":145,"props":688,"children":689},{"style":162},[690],{"type":31,"value":588},{"type":26,"tag":145,"props":692,"children":693},{"class":147,"line":253},[694,698,702,707],{"type":26,"tag":145,"props":695,"children":696},{"style":594},[697],{"type":31,"value":597},{"type":26,"tag":145,"props":699,"children":700},{"style":474},[701],{"type":31,"value":583},{"type":26,"tag":145,"props":703,"children":704},{"style":604},[705],{"type":31,"value":706},"\"User query...\"",{"type":26,"tag":145,"props":708,"children":709},{"style":162},[710],{"type":31,"value":612},{"type":26,"tag":145,"props":712,"children":713},{"class":147,"line":262},[714,718,722],{"type":26,"tag":145,"props":715,"children":716},{"style":594},[717],{"type":31,"value":620},{"type":26,"tag":145,"props":719,"children":720},{"style":474},[721],{"type":31,"value":583},{"type":26,"tag":145,"props":723,"children":724},{"style":604},[725],{"type":31,"value":629},{"type":26,"tag":145,"props":727,"children":728},{"class":147,"line":270},[729,733,737,741,745,749,753],{"type":26,"tag":145,"props":730,"children":731},{"style":162},[732],{"type":31,"value":637},{"type":26,"tag":145,"props":734,"children":735},{"style":604},[736],{"type":31,"value":642},{"type":26,"tag":145,"props":738,"children":739},{"style":162},[740],{"type":31,"value":647},{"type":26,"tag":145,"props":742,"children":743},{"style":650},[744],{"type":31,"value":653},{"type":26,"tag":145,"props":746,"children":747},{"style":162},[748],{"type":31,"value":647},{"type":26,"tag":145,"props":750,"children":751},{"style":604},[752],{"type":31,"value":662},{"type":26,"tag":145,"props":754,"children":755},{"style":162},[756],{"type":31,"value":667},{"type":26,"tag":145,"props":758,"children":760},{"class":147,"line":759},16,[761],{"type":26,"tag":145,"props":762,"children":763},{"emptyLinePlaceholder":180},[764],{"type":31,"value":183},{"type":26,"tag":145,"props":766,"children":768},{"class":147,"line":767},17,[769,774,778],{"type":26,"tag":145,"props":770,"children":771},{"style":162},[772],{"type":31,"value":773},"similarity ",{"type":26,"tag":145,"props":775,"children":776},{"style":474},[777],{"type":31,"value":583},{"type":26,"tag":145,"props":779,"children":780},{"style":162},[781],{"type":31,"value":782}," cosine_similarity(content_embedding, query_embedding)\n",{"type":26,"tag":145,"props":784,"children":786},{"class":147,"line":785},18,[787,792,797,802,807,812,817,822,827,832],{"type":26,"tag":145,"props":788,"children":789},{"style":650},[790],{"type":31,"value":791},"print",{"type":26,"tag":145,"props":793,"children":794},{"style":162},[795],{"type":31,"value":796},"(",{"type":26,"tag":145,"props":798,"children":799},{"style":474},[800],{"type":31,"value":801},"f",{"type":26,"tag":145,"props":803,"children":804},{"style":604},[805],{"type":31,"value":806},"\"Citation probability estimate: ",{"type":26,"tag":145,"props":808,"children":809},{"style":650},[810],{"type":31,"value":811},"{",{"type":26,"tag":145,"props":813,"children":814},{"style":162},[815],{"type":31,"value":816},"similarity",{"type":26,"tag":145,"props":818,"children":819},{"style":474},[820],{"type":31,"value":821},":.2f",{"type":26,"tag":145,"props":823,"children":824},{"style":650},[825],{"type":31,"value":826},"}",{"type":26,"tag":145,"props":828,"children":829},{"style":604},[830],{"type":31,"value":831},"\"",{"type":26,"tag":145,"props":833,"children":834},{"style":162},[835],{"type":31,"value":836},")\n",{"type":26,"tag":27,"props":838,"children":839},{},[840],{"type":31,"value":841},"Integrate this metric into your content pipeline — before publishing, rewrite or semantically expand any content scoring \u003C0.70.",{"type":26,"tag":42,"props":843,"children":845},{"id":844},"competitive-dynamics-and-tradeoffs",[846],{"type":31,"value":847},"Competitive Dynamics and Tradeoffs",{"type":26,"tag":27,"props":849,"children":850},{},[851,853,858],{"type":31,"value":852},"GEO's hidden cost: ",{"type":26,"tag":34,"props":854,"children":855},{},[856],{"type":31,"value":857},"zero-click search increases",{"type":31,"value":859},". The LLM provides a direct answer, the user never visits your site. You get a citation, but no traffic. This is the LLM version of the featured snippet problem. Tradeoff: brand awareness vs. direct traffic. If your conversion funnel depends on top-of-funnel brand recall (e.g., B2B SaaS), GEO works — it builds awareness at the decision stage. If your funnel is transactional (e-commerce checkout), direct traffic matters more; GEO alone is insufficient.",{"type":26,"tag":27,"props":861,"children":862},{},[863,865,870],{"type":31,"value":864},"Second tradeoff: ",{"type":26,"tag":34,"props":866,"children":867},{},[868],{"type":31,"value":869},"content velocity vs. depth",{"type":31,"value":871},". LLMs prioritize fresh content (publication date signals in embedding space). Fast publishing increases citation chances, but shallow content degrades long-term authority. Balanced approach: make core pillar content 2000+ words and deep (GEO anchor), publish supporting content at 800-1000 words rapidly (for freshness). Link supporting content to pillar content — this builds a topical authority cluster. LLMs recognize related content together and signal domain authority.",{"type":26,"tag":27,"props":873,"children":874},{},[875,877,882,884,890,892,897,898,904,905,910,912,918,919,925,927,933,934,940],{"type":31,"value":876},"Third tradeoff: ",{"type":26,"tag":34,"props":878,"children":879},{},[880],{"type":31,"value":881},"schema.org usage",{"type":31,"value":883},". Structured data signals to LLMs, but over-optimization reads as spam. Google's public guidance: use schema but don't overdo it. Critical schemas for GEO: ",{"type":26,"tag":101,"props":885,"children":887},{"className":886},[],[888],{"type":31,"value":889},"Article",{"type":31,"value":891},", ",{"type":26,"tag":101,"props":893,"children":895},{"className":894},[],[896],{"type":31,"value":106},{"type":31,"value":891},{"type":26,"tag":101,"props":899,"children":901},{"className":900},[],[902],{"type":31,"value":903},"HowTo",{"type":31,"value":891},{"type":26,"tag":101,"props":906,"children":908},{"className":907},[],[909],{"type":31,"value":305},{"type":31,"value":911},". ",{"type":26,"tag":101,"props":913,"children":915},{"className":914},[],[916],{"type":31,"value":917},"Organization",{"type":31,"value":403},{"type":26,"tag":101,"props":920,"children":922},{"className":921},[],[923],{"type":31,"value":924},"WebSite",{"type":31,"value":926}," should already exist. Don't add ",{"type":26,"tag":101,"props":928,"children":930},{"className":929},[],[931],{"type":31,"value":932},"Review",{"type":31,"value":362},{"type":26,"tag":101,"props":935,"children":937},{"className":936},[],[938],{"type":31,"value":939},"Product",{"type":31,"value":941}," schema if it doesn't belong — manual action risk, and LLMs detect content-schema mismatch.",{"type":26,"tag":42,"props":943,"children":945},{"id":944},"long-term-strategy-the-ai-first-content-paradigm",[946],{"type":31,"value":947},"Long-Term Strategy — The AI-First Content Paradigm",{"type":26,"tag":27,"props":949,"children":950},{},[951,953,958],{"type":31,"value":952},"Post-2026, content strategy revolves around this axis: ",{"type":26,"tag":34,"props":954,"children":955},{},[956],{"type":31,"value":957},"human-readable, machine-optimized",{"type":31,"value":959},". Content serves both readers and LLMs. This demands token-efficient writing discipline — every word carries signal. Also, prompt engineering mindset must reach your content team. Shift from \"What does the user search?\" to \"In what context does the LLM cite this content?\"",{"type":26,"tag":27,"props":961,"children":962},{},[963],{"type":31,"value":964},"GEO's impact on brand equity emerges over time. Higher citation rates, brand recall, being a reference in decision funnels — these are indirect in attribution models. You may not see direct ROI in the first 6 months, but by month 12, \"organic brand search growth\" and \"assisted conversion rate\" start rising. This mirrors SEO's early days — early adopters gain advantage, late movers lose market share.",{"type":26,"tag":27,"props":966,"children":967},{},[968,970,975,977,983],{"type":31,"value":969},"Final note: ",{"type":26,"tag":34,"props":971,"children":972},{},[973],{"type":31,"value":974},"AI safety and bias risks",{"type":31,"value":976},". LLMs exhibit bias in citation (domain bias, geography bias, language bias). For example, ChatGPT may cite US-based content more frequently than Turkey-based content due to training data skew. GEO strategy must compensate — for Turkish content, add English abstract\u002Fsummary, set ",{"type":26,"tag":101,"props":978,"children":980},{"className":979},[],[981],{"type":31,"value":982},"inLanguage",{"type":31,"value":984}," field in schema explicitly. Appearing in AI overviews means understanding the model's bias and building content architecture accordingly.",{"type":26,"tag":27,"props":986,"children":987},{},[988],{"type":31,"value":989},"GEO is not classical SEO's evolution; it's a new discipline. Optimization for answer engines, not search engines. The attribution window is the LLM's context window, ranking signals are embedding similarity, backlink authority is citation density. In this paradigm, embedding your brand in ChatGPT's answer requires merging prompt engineering with content architecture. First step: audit your existing content inventory through token efficiency and semantic density lenses, rewrite or retire low-citation-potential content. Second step: convert first-party data and unique insights into citable formats. Third step: set up programmatic monitoring, track citation rate weekly, iterate patterns into action.",{"type":26,"tag":991,"props":992,"children":993},"style",{},[994],{"type":31,"value":995},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":9,"searchDepth":168,"depth":168,"links":997},[998,999,1000,1001,1002,1003],{"id":44,"depth":158,"text":47},{"id":72,"depth":158,"text":75},{"id":284,"depth":158,"text":287},{"id":388,"depth":158,"text":391},{"id":844,"depth":158,"text":847},{"id":944,"depth":158,"text":947},"content:en:ai:positioning-your-brand-in-chatgpts-answer.md","content","en\u002Fai\u002Fpositioning-your-brand-in-chatgpts-answer.md","en\u002Fai\u002Fpositioning-your-brand-in-chatgpts-answer","md",{"_path":1010,"_dir":1011,"_draft":8,"_partial":8,"_locale":9,"title":1012,"description":1013,"publishedAt":12,"modifiedAt":12,"category":1011,"i18nKey":1014,"tags":1015,"readingTime":20,"author":21,"body":1021,"_type":139,"_id":1985,"_source":1005,"_file":1986,"_stem":1987,"_extension":1008},"\u002Fen\u002Fmarketing\u002Fserver-side-conversions-setting-up-meta-capi-correctly","marketing","Server-Side Conversions: Setting Up Meta CAPI the Right Way","Complete guide to sGTM + Conversion API architecture, event match quality optimization, deduplication strategies, and first-party data pipelines for post-iOS 17 attribution.","marketing-001-2026-05",[1016,1017,1018,1019,1020],"conversion-api","server-side-gtm","attribution","meta-ads","first-party-data",{"type":23,"children":1022,"toc":1976},[1023,1028,1034,1079,1129,1135,1140,1145,1227,1271,1277,1318,1462,1475,1625,1660,1666,1692,1697,1744,1756,1768,1774,1779,1797,1803,1823,1841,1847,1887,1905,1923,1933,1959,1972],{"type":26,"tag":27,"props":1024,"children":1025},{},[1026],{"type":31,"value":1027},"Since iOS 14.5, browser-based pixel measurement power has dropped 40-60%. According to Meta's 2025 Q4 data, advertisers not using CAPI average an Event Match Quality score below 3.8\u002F10. This means the algorithm lacks sufficient signals to optimize. The cookie-less era's first phase saw browser-side trackers lose ground. The second phase—where server-side architecture either works properly or fails entirely—is happening now. Setting up Meta Conversion API through sGTM is no longer optional. It's infrastructure-level required for performance marketing.",{"type":26,"tag":42,"props":1029,"children":1031},{"id":1030},"why-the-pixel-to-capi-gap-matters",[1032],{"type":31,"value":1033},"Why the pixel-to-CAPI gap matters",{"type":26,"tag":27,"props":1035,"children":1036},{},[1037,1039,1045,1047,1053,1055,1061,1063,1069,1071,1077],{"type":31,"value":1038},"Meta Pixel runs in the browser. It depends on user consent, can't filter bot traffic, and gets hit by network latency. CAPI sends HTTP POST directly from your server to Meta. Two differences matter: timing and data quality. Pixel fires a ",{"type":26,"tag":101,"props":1040,"children":1042},{"className":1041},[],[1043],{"type":31,"value":1044},"PageView",{"type":31,"value":1046}," event when the user loads a page; CAPI can send the same event from your backend after checkout completes. This time gap is where deduplication lives—Meta needs to merge the same event from two sources. Second difference: you control user identifiers in CAPI. Hash ",{"type":26,"tag":101,"props":1048,"children":1050},{"className":1049},[],[1051],{"type":31,"value":1052},"em",{"type":31,"value":1054}," (email), ",{"type":26,"tag":101,"props":1056,"children":1058},{"className":1057},[],[1059],{"type":31,"value":1060},"ph",{"type":31,"value":1062}," (phone), ",{"type":26,"tag":101,"props":1064,"children":1066},{"className":1065},[],[1067],{"type":31,"value":1068},"fbc",{"type":31,"value":1070}," (Facebook click ID), and ",{"type":26,"tag":101,"props":1072,"children":1074},{"className":1073},[],[1075],{"type":31,"value":1076},"fbp",{"type":31,"value":1078}," (browser ID) correctly, or Event Match Quality drops. Low EMQ means the algorithm can't fully understand which user triggered which event. This dulls bid optimization. Meta's 2024 whitepaper showed CAPI + Pixel together deliver 13% average ROAS lift (n=4200 advertisers, 60-day window). But this only happens when deduplication is set up correctly.",{"type":26,"tag":27,"props":1080,"children":1081},{},[1082,1084,1090,1091,1097,1099,1105,1107,1113,1114,1120,1122,1127],{"type":31,"value":1083},"Shutting off the pixel and going CAPI-only is also wrong. Browser pixel captures mid-funnel events like ",{"type":26,"tag":101,"props":1085,"children":1087},{"className":1086},[],[1088],{"type":31,"value":1089},"ViewContent",{"type":31,"value":403},{"type":26,"tag":101,"props":1092,"children":1094},{"className":1093},[],[1095],{"type":31,"value":1096},"AddToCart",{"type":31,"value":1098}," in real time; CAPI typically handles only ",{"type":26,"tag":101,"props":1100,"children":1102},{"className":1101},[],[1103],{"type":31,"value":1104},"Purchase",{"type":31,"value":1106},". You need the middle path: keep the pixel lightweight and send critical conversions through CAPI as duplicates. Deduplication parameters prevent double-counting. Meta's system looks at the ",{"type":26,"tag":101,"props":1108,"children":1110},{"className":1109},[],[1111],{"type":31,"value":1112},"event_id",{"type":31,"value":403},{"type":26,"tag":101,"props":1115,"children":1117},{"className":1116},[],[1118],{"type":31,"value":1119},"event_time",{"type":31,"value":1121}," combo to avoid counting the same action twice. But if you don't pass these parameters identically in both pixel and CAPI, dedup fails. Most implementations break here: frontend generates ",{"type":26,"tag":101,"props":1123,"children":1125},{"className":1124},[],[1126],{"type":31,"value":1112},{"type":31,"value":1128}," as a UUID, backend sends a different ID. Result: two separate events, inflated ROAS reports.",{"type":26,"tag":42,"props":1130,"children":1132},{"id":1131},"building-the-sgtm-infrastructure",[1133],{"type":31,"value":1134},"Building the sGTM infrastructure",{"type":26,"tag":27,"props":1136,"children":1137},{},[1138],{"type":31,"value":1139},"You can set up CAPI without server-side Google Tag Manager—post directly from your backend to Meta. But that approach breaks at scale. Add multiple destinations (Google Ads Enhanced Conversions, TikTok Events API, Snapchat CAPI) and you'll write separate endpoints for each. sGTM provides an abstraction layer: a single server container handles all tagging needs. Host it on Google Cloud Run or App Engine. It catches HTTP requests from your client-side GTM container, fires server-side tags, then sends parallel POSTs to Meta, Google, and TikTok.",{"type":26,"tag":27,"props":1141,"children":1142},{},[1143],{"type":31,"value":1144},"Setup flow:",{"type":26,"tag":412,"props":1146,"children":1147},{},[1148,1166,1192,1202],{"type":26,"tag":416,"props":1149,"children":1150},{},[1151,1156,1158,1164],{"type":26,"tag":34,"props":1152,"children":1153},{},[1154],{"type":31,"value":1155},"Create a Cloud Run instance:",{"type":31,"value":1157}," ",{"type":26,"tag":101,"props":1159,"children":1161},{"className":1160},[],[1162],{"type":31,"value":1163},"gcloud run deploy gtm-server --image=gcr.io\u002Fcloud-tagging-10302018\u002Fgtm-cloud-image:stable --platform=managed --region=europe-west1",{"type":31,"value":1165},". This deploys Google's official sGTM image.",{"type":26,"tag":416,"props":1167,"children":1168},{},[1169,1174,1176,1182,1184,1190],{"type":26,"tag":34,"props":1170,"children":1171},{},[1172],{"type":31,"value":1173},"Get your Tagging Server URL:",{"type":31,"value":1175}," After deployment, you'll have something like ",{"type":26,"tag":101,"props":1177,"children":1179},{"className":1178},[],[1180],{"type":31,"value":1181},"https:\u002F\u002Fgtm-server-xxxxx-ew.a.run.app",{"type":31,"value":1183},". Add this to your client-side GTM as the ",{"type":26,"tag":101,"props":1185,"children":1187},{"className":1186},[],[1188],{"type":31,"value":1189},"serverContainerUrl",{"type":31,"value":1191},".",{"type":26,"tag":416,"props":1193,"children":1194},{},[1195,1200],{"type":26,"tag":34,"props":1196,"children":1197},{},[1198],{"type":31,"value":1199},"Update your GA4 tag in client-side GTM:",{"type":31,"value":1201}," Normally GA4 sends data straight to Google. Set the transport URL to your sGTM endpoint, and GA4 data flows through your server first. This also lets you handle IP anonymization and user-agent normalization server-side.",{"type":26,"tag":416,"props":1203,"children":1204},{},[1205,1210,1212,1218,1219,1225],{"type":26,"tag":34,"props":1206,"children":1207},{},[1208],{"type":31,"value":1209},"Add a Meta CAPI tag in sGTM:",{"type":31,"value":1211}," Use the \"Meta Conversions API\" template. Enter your ",{"type":26,"tag":101,"props":1213,"children":1215},{"className":1214},[],[1216],{"type":31,"value":1217},"Pixel ID",{"type":31,"value":403},{"type":26,"tag":101,"props":1220,"children":1222},{"className":1221},[],[1223],{"type":31,"value":1224},"Access Token",{"type":31,"value":1226},". Get the token from Events Manager > Settings > Conversions API. Test with a test event to confirm the connection.",{"type":26,"tag":27,"props":1228,"children":1229},{},[1230,1232,1238,1240,1246,1248,1253,1255,1260,1262,1269],{"type":31,"value":1231},"sGTM's advantage: you can fire both GA4 and CAPI from a single request. A single ",{"type":26,"tag":101,"props":1233,"children":1235},{"className":1234},[],[1236],{"type":31,"value":1237},"dataLayer.push",{"type":31,"value":1239}," on the client side triggers two server-side tags. No need to write separate API calls in your backend. But watch one thing: GA4's ",{"type":26,"tag":101,"props":1241,"children":1243},{"className":1242},[],[1244],{"type":31,"value":1245},"client_id",{"type":31,"value":1247}," isn't Meta's ",{"type":26,"tag":101,"props":1249,"children":1251},{"className":1250},[],[1252],{"type":31,"value":1076},{"type":31,"value":1254},". Create a transformation variable in sGTM to map the ",{"type":26,"tag":101,"props":1256,"children":1258},{"className":1257},[],[1259],{"type":31,"value":1076},{"type":31,"value":1261}," cookie to the CAPI tag. This mapping requires ",{"type":26,"tag":326,"props":1263,"children":1266},{"href":1264,"rel":1265},"https:\u002F\u002Fwww.roibase.com.tr\u002Fen\u002Fppc",[330],[1267],{"type":31,"value":1268},"first-party data architecture",{"type":31,"value":1270},"; without it, identifiers won't sync and EMQ drops.",{"type":26,"tag":42,"props":1272,"children":1274},{"id":1273},"raising-event-match-quality",[1275],{"type":31,"value":1276},"Raising Event Match Quality",{"type":26,"tag":27,"props":1278,"children":1279},{},[1280,1282,1287,1289,1294,1296,1302,1304,1309,1311,1316],{"type":31,"value":1281},"EMQ is Meta's confidence score for \"which user gets this event.\" Max is 10. Above 8 is excellent; below 6 is problematic. Right identifier combinations raise EMQ. Meta's priority order: ",{"type":26,"tag":101,"props":1283,"children":1285},{"className":1284},[],[1286],{"type":31,"value":1052},{"type":31,"value":1288}," (email) > ",{"type":26,"tag":101,"props":1290,"children":1292},{"className":1291},[],[1293],{"type":31,"value":1060},{"type":31,"value":1295}," (phone) > ",{"type":26,"tag":101,"props":1297,"children":1299},{"className":1298},[],[1300],{"type":31,"value":1301},"external_id",{"type":31,"value":1303}," (CRM ID) > ",{"type":26,"tag":101,"props":1305,"children":1307},{"className":1306},[],[1308],{"type":31,"value":1068},{"type":31,"value":1310}," > ",{"type":26,"tag":101,"props":1312,"children":1314},{"className":1313},[],[1315],{"type":31,"value":1076},{"type":31,"value":1317},". Hash email and phone with SHA-256, lowercase, no whitespace. Example:",{"type":26,"tag":135,"props":1319,"children":1323},{"className":1320,"code":1321,"language":1322,"meta":9,"style":9},"language-javascript shiki shiki-themes github-dark","\u002F\u002F Wrong hash\nconst email = \" John@Example.com \";\nconst hash = sha256(email); \u002F\u002F Spaces and caps cause problems\n\n\u002F\u002F Correct hash\nconst email = \"john@example.com\";\nconst hash = sha256(email); \u002F\u002F SHA-256: a665a...\n","javascript",[1324],{"type":26,"tag":101,"props":1325,"children":1326},{"__ignoreMap":9},[1327,1336,1364,1395,1402,1410,1434],{"type":26,"tag":145,"props":1328,"children":1329},{"class":147,"line":148},[1330],{"type":26,"tag":145,"props":1331,"children":1333},{"style":1332},"--shiki-default:#6A737D",[1334],{"type":31,"value":1335},"\u002F\u002F Wrong hash\n",{"type":26,"tag":145,"props":1337,"children":1338},{"class":147,"line":158},[1339,1344,1349,1354,1359],{"type":26,"tag":145,"props":1340,"children":1341},{"style":474},[1342],{"type":31,"value":1343},"const",{"type":26,"tag":145,"props":1345,"children":1346},{"style":650},[1347],{"type":31,"value":1348}," email",{"type":26,"tag":145,"props":1350,"children":1351},{"style":474},[1352],{"type":31,"value":1353}," =",{"type":26,"tag":145,"props":1355,"children":1356},{"style":604},[1357],{"type":31,"value":1358}," \" John@Example.com \"",{"type":26,"tag":145,"props":1360,"children":1361},{"style":162},[1362],{"type":31,"value":1363},";\n",{"type":26,"tag":145,"props":1365,"children":1366},{"class":147,"line":168},[1367,1371,1376,1380,1385,1390],{"type":26,"tag":145,"props":1368,"children":1369},{"style":474},[1370],{"type":31,"value":1343},{"type":26,"tag":145,"props":1372,"children":1373},{"style":650},[1374],{"type":31,"value":1375}," hash",{"type":26,"tag":145,"props":1377,"children":1378},{"style":474},[1379],{"type":31,"value":1353},{"type":26,"tag":145,"props":1381,"children":1382},{"style":522},[1383],{"type":31,"value":1384}," sha256",{"type":26,"tag":145,"props":1386,"children":1387},{"style":162},[1388],{"type":31,"value":1389},"(email); ",{"type":26,"tag":145,"props":1391,"children":1392},{"style":1332},[1393],{"type":31,"value":1394},"\u002F\u002F Spaces and caps cause problems\n",{"type":26,"tag":145,"props":1396,"children":1397},{"class":147,"line":176},[1398],{"type":26,"tag":145,"props":1399,"children":1400},{"emptyLinePlaceholder":180},[1401],{"type":31,"value":183},{"type":26,"tag":145,"props":1403,"children":1404},{"class":147,"line":186},[1405],{"type":26,"tag":145,"props":1406,"children":1407},{"style":1332},[1408],{"type":31,"value":1409},"\u002F\u002F Correct hash\n",{"type":26,"tag":145,"props":1411,"children":1412},{"class":147,"line":195},[1413,1417,1421,1425,1430],{"type":26,"tag":145,"props":1414,"children":1415},{"style":474},[1416],{"type":31,"value":1343},{"type":26,"tag":145,"props":1418,"children":1419},{"style":650},[1420],{"type":31,"value":1348},{"type":26,"tag":145,"props":1422,"children":1423},{"style":474},[1424],{"type":31,"value":1353},{"type":26,"tag":145,"props":1426,"children":1427},{"style":604},[1428],{"type":31,"value":1429}," \"john@example.com\"",{"type":26,"tag":145,"props":1431,"children":1432},{"style":162},[1433],{"type":31,"value":1363},{"type":26,"tag":145,"props":1435,"children":1436},{"class":147,"line":203},[1437,1441,1445,1449,1453,1457],{"type":26,"tag":145,"props":1438,"children":1439},{"style":474},[1440],{"type":31,"value":1343},{"type":26,"tag":145,"props":1442,"children":1443},{"style":650},[1444],{"type":31,"value":1375},{"type":26,"tag":145,"props":1446,"children":1447},{"style":474},[1448],{"type":31,"value":1353},{"type":26,"tag":145,"props":1450,"children":1451},{"style":522},[1452],{"type":31,"value":1384},{"type":26,"tag":145,"props":1454,"children":1455},{"style":162},[1456],{"type":31,"value":1389},{"type":26,"tag":145,"props":1458,"children":1459},{"style":1332},[1460],{"type":31,"value":1461},"\u002F\u002F SHA-256: a665a...\n",{"type":26,"tag":27,"props":1463,"children":1464},{},[1465,1467,1473],{"type":31,"value":1466},"Your CAPI ",{"type":26,"tag":101,"props":1468,"children":1470},{"className":1469},[],[1471],{"type":31,"value":1472},"user_data",{"type":31,"value":1474}," object should look like this:",{"type":26,"tag":135,"props":1476,"children":1480},{"className":1477,"code":1478,"language":1479,"meta":9,"style":9},"language-json shiki shiki-themes github-dark","{\n  \"em\": [\"a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3\"],\n  \"ph\": [\"sha256_phone_hash\"],\n  \"fbc\": \"fb.1.1554763741205.AbCdEfGhIjKlMnOpQrStUvWxYz\",\n  \"fbp\": \"fb.1.1558571054389.1098115397\",\n  \"client_ip_address\": \"93.184.216.34\",\n  \"client_user_agent\": \"Mozilla\u002F5.0...\"\n}\n","json",[1481],{"type":26,"tag":101,"props":1482,"children":1483},{"__ignoreMap":9},[1484,1492,1515,1536,1558,1579,1600,1617],{"type":26,"tag":145,"props":1485,"children":1486},{"class":147,"line":148},[1487],{"type":26,"tag":145,"props":1488,"children":1489},{"style":162},[1490],{"type":31,"value":1491},"{\n",{"type":26,"tag":145,"props":1493,"children":1494},{"class":147,"line":158},[1495,1500,1505,1510],{"type":26,"tag":145,"props":1496,"children":1497},{"style":650},[1498],{"type":31,"value":1499},"  \"em\"",{"type":26,"tag":145,"props":1501,"children":1502},{"style":162},[1503],{"type":31,"value":1504},": [",{"type":26,"tag":145,"props":1506,"children":1507},{"style":604},[1508],{"type":31,"value":1509},"\"a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3\"",{"type":26,"tag":145,"props":1511,"children":1512},{"style":162},[1513],{"type":31,"value":1514},"],\n",{"type":26,"tag":145,"props":1516,"children":1517},{"class":147,"line":168},[1518,1523,1527,1532],{"type":26,"tag":145,"props":1519,"children":1520},{"style":650},[1521],{"type":31,"value":1522},"  \"ph\"",{"type":26,"tag":145,"props":1524,"children":1525},{"style":162},[1526],{"type":31,"value":1504},{"type":26,"tag":145,"props":1528,"children":1529},{"style":604},[1530],{"type":31,"value":1531},"\"sha256_phone_hash\"",{"type":26,"tag":145,"props":1533,"children":1534},{"style":162},[1535],{"type":31,"value":1514},{"type":26,"tag":145,"props":1537,"children":1538},{"class":147,"line":176},[1539,1544,1549,1554],{"type":26,"tag":145,"props":1540,"children":1541},{"style":650},[1542],{"type":31,"value":1543},"  \"fbc\"",{"type":26,"tag":145,"props":1545,"children":1546},{"style":162},[1547],{"type":31,"value":1548},": ",{"type":26,"tag":145,"props":1550,"children":1551},{"style":604},[1552],{"type":31,"value":1553},"\"fb.1.1554763741205.AbCdEfGhIjKlMnOpQrStUvWxYz\"",{"type":26,"tag":145,"props":1555,"children":1556},{"style":162},[1557],{"type":31,"value":612},{"type":26,"tag":145,"props":1559,"children":1560},{"class":147,"line":186},[1561,1566,1570,1575],{"type":26,"tag":145,"props":1562,"children":1563},{"style":650},[1564],{"type":31,"value":1565},"  \"fbp\"",{"type":26,"tag":145,"props":1567,"children":1568},{"style":162},[1569],{"type":31,"value":1548},{"type":26,"tag":145,"props":1571,"children":1572},{"style":604},[1573],{"type":31,"value":1574},"\"fb.1.1558571054389.1098115397\"",{"type":26,"tag":145,"props":1576,"children":1577},{"style":162},[1578],{"type":31,"value":612},{"type":26,"tag":145,"props":1580,"children":1581},{"class":147,"line":195},[1582,1587,1591,1596],{"type":26,"tag":145,"props":1583,"children":1584},{"style":650},[1585],{"type":31,"value":1586},"  \"client_ip_address\"",{"type":26,"tag":145,"props":1588,"children":1589},{"style":162},[1590],{"type":31,"value":1548},{"type":26,"tag":145,"props":1592,"children":1593},{"style":604},[1594],{"type":31,"value":1595},"\"93.184.216.34\"",{"type":26,"tag":145,"props":1597,"children":1598},{"style":162},[1599],{"type":31,"value":612},{"type":26,"tag":145,"props":1601,"children":1602},{"class":147,"line":203},[1603,1608,1612],{"type":26,"tag":145,"props":1604,"children":1605},{"style":650},[1606],{"type":31,"value":1607},"  \"client_user_agent\"",{"type":26,"tag":145,"props":1609,"children":1610},{"style":162},[1611],{"type":31,"value":1548},{"type":26,"tag":145,"props":1613,"children":1614},{"style":604},[1615],{"type":31,"value":1616},"\"Mozilla\u002F5.0...\"\n",{"type":26,"tag":145,"props":1618,"children":1619},{"class":147,"line":20},[1620],{"type":26,"tag":145,"props":1621,"children":1622},{"style":162},[1623],{"type":31,"value":1624},"}\n",{"type":26,"tag":27,"props":1626,"children":1627},{},[1628,1630,1636,1638,1643,1645,1651,1653,1658],{"type":31,"value":1629},"sGTM auto-captures IP and user agent, but some hosting (Cloudflare proxy) requires parsing the ",{"type":26,"tag":101,"props":1631,"children":1633},{"className":1632},[],[1634],{"type":31,"value":1635},"X-Forwarded-For",{"type":31,"value":1637}," header. The ",{"type":26,"tag":101,"props":1639,"children":1641},{"className":1640},[],[1642],{"type":31,"value":1068},{"type":31,"value":1644}," parameter is the Facebook click ID—when a user clicks a Meta ad, the URL gets ",{"type":26,"tag":101,"props":1646,"children":1648},{"className":1647},[],[1649],{"type":31,"value":1650},"fbclid=...",{"type":31,"value":1652},". Write this to a cookie and send it to CAPI to close the attribution loop. Most implementations skip ",{"type":26,"tag":101,"props":1654,"children":1656},{"className":1655},[],[1657],{"type":31,"value":1068},{"type":31,"value":1659},", so Meta never knows which ad drove the conversion. EMQ stays at 4.2.",{"type":26,"tag":42,"props":1661,"children":1663},{"id":1662},"deduplication-strategy",[1664],{"type":31,"value":1665},"Deduplication strategy",{"type":26,"tag":27,"props":1667,"children":1668},{},[1669,1671,1676,1678,1683,1685,1690],{"type":31,"value":1670},"When the same ",{"type":26,"tag":101,"props":1672,"children":1674},{"className":1673},[],[1675],{"type":31,"value":1104},{"type":31,"value":1677}," event arrives from both pixel and CAPI, Meta counts it once if ",{"type":26,"tag":101,"props":1679,"children":1681},{"className":1680},[],[1682],{"type":31,"value":1112},{"type":31,"value":1684}," matches. Usually a UUID v4. But if the frontend generates the ID, the backend must use it too. Solution: add ",{"type":26,"tag":101,"props":1686,"children":1688},{"className":1687},[],[1689],{"type":31,"value":1112},{"type":31,"value":1691}," as a hidden input during checkout or store it in localStorage. When the backend completes the order, it grabs the same ID for the CAPI request. Time gap must stay within 48 hours (Meta's dedup window). Beyond 48 hours, it's two separate events.",{"type":26,"tag":27,"props":1693,"children":1694},{},[1695],{"type":31,"value":1696},"Example flow:",{"type":26,"tag":412,"props":1698,"children":1699},{},[1700,1721,1739],{"type":26,"tag":416,"props":1701,"children":1702},{},[1703,1705,1711,1713,1719],{"type":31,"value":1704},"User clicks \"Buy Now\" → pixel fires ",{"type":26,"tag":101,"props":1706,"children":1708},{"className":1707},[],[1709],{"type":31,"value":1710},"InitiateCheckout",{"type":31,"value":1712}," (event_id: ",{"type":26,"tag":101,"props":1714,"children":1716},{"className":1715},[],[1717],{"type":31,"value":1718},"evt_12345",{"type":31,"value":1720},", event_time: 1683820800)",{"type":26,"tag":416,"props":1722,"children":1723},{},[1724,1726,1731,1732,1737],{"type":31,"value":1725},"Backend approves payment → CAPI sends ",{"type":26,"tag":101,"props":1727,"children":1729},{"className":1728},[],[1730],{"type":31,"value":1104},{"type":31,"value":1712},{"type":26,"tag":101,"props":1733,"children":1735},{"className":1734},[],[1736],{"type":31,"value":1718},{"type":31,"value":1738},", event_time: 1683820802)",{"type":26,"tag":416,"props":1740,"children":1741},{},[1742],{"type":31,"value":1743},"Meta sees both, IDs match, 2-second gap → counts as one event.",{"type":26,"tag":27,"props":1745,"children":1746},{},[1747,1749,1754],{"type":31,"value":1748},"Without this, pixel and CAPI ",{"type":26,"tag":101,"props":1750,"children":1752},{"className":1751},[],[1753],{"type":31,"value":1104},{"type":31,"value":1755}," events both count. ROAS inflates. You see \"100 conversions\" on the dashboard but reality is 50. Wrong budget allocation follows.",{"type":26,"tag":27,"props":1757,"children":1758},{},[1759,1761,1766],{"type":31,"value":1760},"Sometimes the pixel event gets lost (ad blocker, no consent). CAPI alone works fine then. No dedup issue. But if the pixel fires late (user was offline, browser queue released the event 10 minutes later) and the ID is wrong, Meta counts it as new. Handle this edge case by locking server-side ",{"type":26,"tag":101,"props":1762,"children":1764},{"className":1763},[],[1765],{"type":31,"value":1119},{"type":31,"value":1767}," to your backend's order timestamp, not the user's browser clock.",{"type":26,"tag":42,"props":1769,"children":1771},{"id":1770},"incrementality-and-testing-capi",[1772],{"type":31,"value":1773},"Incrementality and testing CAPI",{"type":26,"tag":27,"props":1775,"children":1776},{},[1777],{"type":31,"value":1778},"EMQ 8.5 and working dedup aren't enough. Real question: would these conversions happen without CAPI? Geo-based holdout tests or conversion lift studies answer this. Meta's Conversion Lift tool exists but needs high spend ($30k+). Alternative: simple A\u002FB test. Run CAPI on half your traffic, disable it on the other half. After 14 days, check incremental ROAS. If CAPI group performs 15% better, you've proven the infrastructure's value.",{"type":26,"tag":27,"props":1780,"children":1781},{},[1782,1784,1789,1790,1795],{"type":31,"value":1783},"Another metric: attribution windows. CAPI improves 7-day click attribution reliability because post-click events come from your backend—real users, not bots. Pixel sees 8-12% bot traffic. CAPI with server IP whitelist drops below 1%. Campaign optimization runs on cleaner signals. Some advertisers ditched the pixel entirely, CAPI-only (especially B2B lead gen). Risky for ecommerce though—you lose ",{"type":26,"tag":101,"props":1785,"children":1787},{"className":1786},[],[1788],{"type":31,"value":1089},{"type":31,"value":403},{"type":26,"tag":101,"props":1791,"children":1793},{"className":1792},[],[1794],{"type":31,"value":1096},{"type":31,"value":1796}," signals. Dynamic retargeting audiences weaken.",{"type":26,"tag":42,"props":1798,"children":1800},{"id":1799},"advanced-custom-events-and-offline-conversions",[1801],{"type":31,"value":1802},"Advanced: custom events and offline conversions",{"type":26,"tag":27,"props":1804,"children":1805},{},[1806,1808,1814,1815,1821],{"type":31,"value":1807},"CAPI isn't limited to standard events. Define custom ones and send from your backend. Examples: ",{"type":26,"tag":101,"props":1809,"children":1811},{"className":1810},[],[1812],{"type":31,"value":1813},"SubscriptionRenewal",{"type":31,"value":362},{"type":26,"tag":101,"props":1816,"children":1818},{"className":1817},[],[1819],{"type":31,"value":1820},"TrialStarted",{"type":31,"value":1822},". Define them as custom conversions and set them as campaign optimization objectives. SaaS especially benefits: send long-term events (90-day retention, upsell) through CAPI to optimize lifetime value. Similar to Google Ads' offline conversion import.",{"type":26,"tag":27,"props":1824,"children":1825},{},[1826,1828,1833,1834,1839],{"type":31,"value":1827},"Offline conversion scenario: user fills an online lead form, sales closes the deal by phone 5 days later. Export that deal from your CRM and send it to CAPI as a ",{"type":26,"tag":101,"props":1829,"children":1831},{"className":1830},[],[1832],{"type":31,"value":1104},{"type":31,"value":911},{"type":26,"tag":101,"props":1835,"children":1837},{"className":1836},[],[1838],{"type":31,"value":1119},{"type":31,"value":1840}," will be past-dated. Meta accepts events up to 62 days old. But this event's impact on optimization is limited—algorithms optimize on real-time signals. Still necessary for reporting accuracy. Automate CRM-to-CAPI with Zapier or n8n; trigger a CAPI POST each time a deal closes.",{"type":26,"tag":42,"props":1842,"children":1844},{"id":1843},"common-mistakes-and-fixes",[1845],{"type":31,"value":1846},"Common mistakes and fixes",{"type":26,"tag":27,"props":1848,"children":1849},{},[1850,1862,1864,1870,1872,1878,1880,1885],{"type":26,"tag":34,"props":1851,"children":1852},{},[1853,1855,1860],{"type":31,"value":1854},"1. Missing ",{"type":26,"tag":101,"props":1856,"children":1858},{"className":1857},[],[1859],{"type":31,"value":1068},{"type":31,"value":1861}," parameter:",{"type":31,"value":1863}," User clicks a Meta ad, lands on your site with ",{"type":26,"tag":101,"props":1865,"children":1867},{"className":1866},[],[1868],{"type":31,"value":1869},"fbclid",{"type":31,"value":1871}," in the URL. If you don't store this in a cookie, you can't send it to CAPI. Fix: create a GTM cookie variable named ",{"type":26,"tag":101,"props":1873,"children":1875},{"className":1874},[],[1876],{"type":31,"value":1877},"_fbc",{"type":31,"value":1879},", set 90-day expiry, map it to ",{"type":26,"tag":101,"props":1881,"children":1883},{"className":1882},[],[1884],{"type":31,"value":1068},{"type":31,"value":1886}," in your CAPI tag.",{"type":26,"tag":27,"props":1888,"children":1889},{},[1890,1895,1897,1903],{"type":26,"tag":34,"props":1891,"children":1892},{},[1893],{"type":31,"value":1894},"2. Wrong email hash:",{"type":31,"value":1896}," Leftover spaces or caps mean no hash match. Always ",{"type":26,"tag":101,"props":1898,"children":1900},{"className":1899},[],[1901],{"type":31,"value":1902},"trim().toLowerCase()",{"type":31,"value":1904}," before SHA-256.",{"type":26,"tag":27,"props":1906,"children":1907},{},[1908,1913,1915,1921],{"type":26,"tag":34,"props":1909,"children":1910},{},[1911],{"type":31,"value":1912},"3. Still in test mode:",{"type":31,"value":1914}," Test events show in Events Manager's \"Test Events\" tab but real traffic doesn't flow. Remove the ",{"type":26,"tag":101,"props":1916,"children":1918},{"className":1917},[],[1919],{"type":31,"value":1920},"test_event_code",{"type":31,"value":1922}," parameter and use your production token.",{"type":26,"tag":27,"props":1924,"children":1925},{},[1926,1931],{"type":26,"tag":34,"props":1927,"children":1928},{},[1929],{"type":31,"value":1930},"4. Ignoring server container logs:",{"type":31,"value":1932}," sGTM Cloud Run logs show CAPI responses. Anything other than 200 OK (401, 400, etc.) means bad token or payload.",{"type":26,"tag":27,"props":1934,"children":1935},{},[1936,1941,1943,1949,1951,1957],{"type":26,"tag":34,"props":1937,"children":1938},{},[1939],{"type":31,"value":1940},"5. Data type mismatch between pixel and CAPI:",{"type":31,"value":1942}," Pixel sends ",{"type":26,"tag":101,"props":1944,"children":1946},{"className":1945},[],[1947],{"type":31,"value":1948},"value",{"type":31,"value":1950}," as float, CAPI as integer. Meta may round currency. Fix: use ",{"type":26,"tag":101,"props":1952,"children":1954},{"className":1953},[],[1955],{"type":31,"value":1956},"value: parseFloat(orderTotal).toFixed(2)",{"type":31,"value":1958}," on both.",{"type":26,"tag":27,"props":1960,"children":1961},{},[1962,1964,1970],{"type":31,"value":1963},"One last point: CAPI setup isn't \"set and forget.\" iOS updates, Meta API version changes, new identifier types (",{"type":26,"tag":101,"props":1965,"children":1967},{"className":1966},[],[1968],{"type":31,"value":1969},"anon_id",{"type":31,"value":1971}," entered beta in 2025)—all require ongoing maintenance. Track EMQ monthly; if it drops below 8, review identifier mapping. Check deduplication rate too: should be 95%+ (95% of pixel+CAPI events successfully deduped). You won't find this in Meta Events Manager; build your own log pipeline. Write request IDs from sGTM to BigQuery, then compare.",{"type":26,"tag":991,"props":1973,"children":1974},{},[1975],{"type":31,"value":995},{"title":9,"searchDepth":168,"depth":168,"links":1977},[1978,1979,1980,1981,1982,1983,1984],{"id":1030,"depth":158,"text":1033},{"id":1131,"depth":158,"text":1134},{"id":1273,"depth":158,"text":1276},{"id":1662,"depth":158,"text":1665},{"id":1770,"depth":158,"text":1773},{"id":1799,"depth":158,"text":1802},{"id":1843,"depth":158,"text":1846},"content:en:marketing:server-side-conversions-setting-up-meta-capi-correctly.md","en\u002Fmarketing\u002Fserver-side-conversions-setting-up-meta-capi-correctly.md","en\u002Fmarketing\u002Fserver-side-conversions-setting-up-meta-capi-correctly",{"_path":1989,"_dir":1990,"_draft":8,"_partial":8,"_locale":9,"title":1991,"description":1992,"publishedAt":12,"modifiedAt":12,"category":1990,"i18nKey":1993,"tags":1994,"readingTime":20,"author":21,"body":2000,"_type":139,"_id":3464,"_source":1005,"_file":3465,"_stem":3466,"_extension":1008},"\u002Fen\u002Ftech\u002Fnuxt-3-cloudflare-pages-lcp-optimization","tech","Nuxt 3 + Cloudflare Pages: From 10s to 2s LCP","Self-hosted fonts, lazy hydration, content-visibility, and edge caching reduced LCP by 80%. Real benchmarks, code examples, and tradeoffs.","tech-001-2026-05",[1995,1996,1997,1998,1999],"nuxt3","cloudflare-pages","web-performance","lcp","edge-caching",{"type":23,"children":2001,"toc":3453},[2002,2007,2013,2018,2062,2067,2073,2110,2479,2496,2508,2528,2635,2648,2733,2755,2761,2782,2926,2936,2951,2957,2969,3131,3144,3161,3167,3172,3302,3316,3322,3353,3363,3373,3390,3396,3401,3444,3449],{"type":26,"tag":27,"props":2003,"children":2004},{},[2005],{"type":31,"value":2006},"After Google's Core Web Vitals update, LCP (Largest Contentful Paint) must stay below 2.5 seconds—otherwise both organic rankings and conversion rates suffer. When we migrated an e-commerce site to Nuxt 3 + Cloudflare Pages, initial deployment landed LCP at 10.2 seconds. Combining self-hosted fonts, selective hydration, CSS content-visibility, and edge caching brought it down to 2.1 seconds. Below, we detail step-by-step which change delivered which gain, the tradeoffs, and the code.",{"type":26,"tag":42,"props":2008,"children":2010},{"id":2009},"diagnosing-the-problem-anatomy-of-10s-lcp",[2011],{"type":31,"value":2012},"Diagnosing the problem: anatomy of 10s LCP",{"type":26,"tag":27,"props":2014,"children":2015},{},[2016],{"type":31,"value":2017},"The initial CrUX report showed median LCP 10.2s and TBT (Total Blocking Time) 2190ms. Chrome DevTools Lighthouse profiling revealed:",{"type":26,"tag":2019,"props":2020,"children":2021},"ul",{},[2022,2032,2042,2052],{"type":26,"tag":416,"props":2023,"children":2024},{},[2025,2030],{"type":26,"tag":34,"props":2026,"children":2027},{},[2028],{"type":31,"value":2029},"Font loading:",{"type":31,"value":2031}," Three font families from Google Fonts CDN, render-blocking",{"type":26,"tag":416,"props":2033,"children":2034},{},[2035,2040],{"type":26,"tag":34,"props":2036,"children":2037},{},[2038],{"type":31,"value":2039},"JavaScript hydration:",{"type":31,"value":2041}," 420kB bundle, entire page hydrated",{"type":26,"tag":416,"props":2043,"children":2044},{},[2045,2050],{"type":26,"tag":34,"props":2046,"children":2047},{},[2048],{"type":31,"value":2049},"Above-the-fold image:",{"type":31,"value":2051}," 1.2MB JPEG, no lazy loading",{"type":26,"tag":416,"props":2053,"children":2054},{},[2055,2060],{"type":26,"tag":34,"props":2056,"children":2057},{},[2058],{"type":31,"value":2059},"Cloudflare cache:",{"type":31,"value":2061}," SSR responses not cached, every request hits origin",{"type":26,"tag":27,"props":2063,"children":2064},{},[2065],{"type":31,"value":2066},"Baseline: PageSpeed Insights mobile score 34\u002F100, desktop 62\u002F100. These numbers came after migrating from Shopify Liquid to Nuxt 3—framework change alone doesn't deliver performance gains; architectural optimization is essential.",{"type":26,"tag":42,"props":2068,"children":2070},{"id":2069},"self-hosted-fonts-preload-strategy",[2071],{"type":31,"value":2072},"Self-hosted fonts + preload strategy",{"type":26,"tag":27,"props":2074,"children":2075},{},[2076,2078,2084,2086,2092,2094,2100,2102,2108],{"type":31,"value":2077},"We downloaded the same font files from Google Fonts into ",{"type":26,"tag":101,"props":2079,"children":2081},{"className":2080},[],[2082],{"type":31,"value":2083},"public\u002Ffonts\u002F",{"type":31,"value":2085}," and moved the ",{"type":26,"tag":101,"props":2087,"children":2089},{"className":2088},[],[2090],{"type":31,"value":2091},"@font-face",{"type":31,"value":2093}," declaration to ",{"type":26,"tag":101,"props":2095,"children":2097},{"className":2096},[],[2098],{"type":31,"value":2099},"app.vue",{"type":31,"value":2101},". The critical difference: using ",{"type":26,"tag":101,"props":2103,"children":2105},{"className":2104},[],[2106],{"type":31,"value":2107},"\u003Clink rel=\"preload\">",{"type":31,"value":2109}," triggers font file requests inside the initial HTML response, before CSS is parsed.",{"type":26,"tag":135,"props":2111,"children":2115},{"className":2112,"code":2113,"language":2114,"meta":9,"style":9},"language-vue shiki shiki-themes github-dark","\u003C!-- app.vue -->\n\u003Cscript setup>\nuseHead({\n  link: [\n    {\n      rel: 'preload',\n      href: '\u002Ffonts\u002Finter-var.woff2',\n      as: 'font',\n      type: 'font\u002Fwoff2',\n      crossorigin: 'anonymous'\n    }\n  ]\n})\n\u003C\u002Fscript>\n\n\u003Cstyle>\n@font-face {\n  font-family: 'Inter';\n  src: url('\u002Ffonts\u002Finter-var.woff2') format('woff2');\n  font-display: swap;\n  font-weight: 100 900;\n}\n\u003C\u002Fstyle>\n","vue",[2116],{"type":26,"tag":101,"props":2117,"children":2118},{"__ignoreMap":9},[2119,2127,2151,2164,2172,2180,2197,2214,2231,2248,2261,2269,2277,2285,2301,2308,2323,2335,2356,2406,2428,2455,2463],{"type":26,"tag":145,"props":2120,"children":2121},{"class":147,"line":148},[2122],{"type":26,"tag":145,"props":2123,"children":2124},{"style":1332},[2125],{"type":31,"value":2126},"\u003C!-- app.vue -->\n",{"type":26,"tag":145,"props":2128,"children":2129},{"class":147,"line":158},[2130,2135,2141,2146],{"type":26,"tag":145,"props":2131,"children":2132},{"style":162},[2133],{"type":31,"value":2134},"\u003C",{"type":26,"tag":145,"props":2136,"children":2138},{"style":2137},"--shiki-default:#85E89D",[2139],{"type":31,"value":2140},"script",{"type":26,"tag":145,"props":2142,"children":2143},{"style":522},[2144],{"type":31,"value":2145}," setup",{"type":26,"tag":145,"props":2147,"children":2148},{"style":162},[2149],{"type":31,"value":2150},">\n",{"type":26,"tag":145,"props":2152,"children":2153},{"class":147,"line":168},[2154,2159],{"type":26,"tag":145,"props":2155,"children":2156},{"style":522},[2157],{"type":31,"value":2158},"useHead",{"type":26,"tag":145,"props":2160,"children":2161},{"style":162},[2162],{"type":31,"value":2163},"({\n",{"type":26,"tag":145,"props":2165,"children":2166},{"class":147,"line":176},[2167],{"type":26,"tag":145,"props":2168,"children":2169},{"style":162},[2170],{"type":31,"value":2171},"  link: [\n",{"type":26,"tag":145,"props":2173,"children":2174},{"class":147,"line":186},[2175],{"type":26,"tag":145,"props":2176,"children":2177},{"style":162},[2178],{"type":31,"value":2179},"    {\n",{"type":26,"tag":145,"props":2181,"children":2182},{"class":147,"line":195},[2183,2188,2193],{"type":26,"tag":145,"props":2184,"children":2185},{"style":162},[2186],{"type":31,"value":2187},"      rel: ",{"type":26,"tag":145,"props":2189,"children":2190},{"style":604},[2191],{"type":31,"value":2192},"'preload'",{"type":26,"tag":145,"props":2194,"children":2195},{"style":162},[2196],{"type":31,"value":612},{"type":26,"tag":145,"props":2198,"children":2199},{"class":147,"line":203},[2200,2205,2210],{"type":26,"tag":145,"props":2201,"children":2202},{"style":162},[2203],{"type":31,"value":2204},"      href: ",{"type":26,"tag":145,"props":2206,"children":2207},{"style":604},[2208],{"type":31,"value":2209},"'\u002Ffonts\u002Finter-var.woff2'",{"type":26,"tag":145,"props":2211,"children":2212},{"style":162},[2213],{"type":31,"value":612},{"type":26,"tag":145,"props":2215,"children":2216},{"class":147,"line":20},[2217,2222,2227],{"type":26,"tag":145,"props":2218,"children":2219},{"style":162},[2220],{"type":31,"value":2221},"      as: ",{"type":26,"tag":145,"props":2223,"children":2224},{"style":604},[2225],{"type":31,"value":2226},"'font'",{"type":26,"tag":145,"props":2228,"children":2229},{"style":162},[2230],{"type":31,"value":612},{"type":26,"tag":145,"props":2232,"children":2233},{"class":147,"line":219},[2234,2239,2244],{"type":26,"tag":145,"props":2235,"children":2236},{"style":162},[2237],{"type":31,"value":2238},"      type: ",{"type":26,"tag":145,"props":2240,"children":2241},{"style":604},[2242],{"type":31,"value":2243},"'font\u002Fwoff2'",{"type":26,"tag":145,"props":2245,"children":2246},{"style":162},[2247],{"type":31,"value":612},{"type":26,"tag":145,"props":2249,"children":2250},{"class":147,"line":228},[2251,2256],{"type":26,"tag":145,"props":2252,"children":2253},{"style":162},[2254],{"type":31,"value":2255},"      crossorigin: ",{"type":26,"tag":145,"props":2257,"children":2258},{"style":604},[2259],{"type":31,"value":2260},"'anonymous'\n",{"type":26,"tag":145,"props":2262,"children":2263},{"class":147,"line":236},[2264],{"type":26,"tag":145,"props":2265,"children":2266},{"style":162},[2267],{"type":31,"value":2268},"    }\n",{"type":26,"tag":145,"props":2270,"children":2271},{"class":147,"line":245},[2272],{"type":26,"tag":145,"props":2273,"children":2274},{"style":162},[2275],{"type":31,"value":2276},"  ]\n",{"type":26,"tag":145,"props":2278,"children":2279},{"class":147,"line":253},[2280],{"type":26,"tag":145,"props":2281,"children":2282},{"style":162},[2283],{"type":31,"value":2284},"})\n",{"type":26,"tag":145,"props":2286,"children":2287},{"class":147,"line":262},[2288,2293,2297],{"type":26,"tag":145,"props":2289,"children":2290},{"style":162},[2291],{"type":31,"value":2292},"\u003C\u002F",{"type":26,"tag":145,"props":2294,"children":2295},{"style":2137},[2296],{"type":31,"value":2140},{"type":26,"tag":145,"props":2298,"children":2299},{"style":162},[2300],{"type":31,"value":2150},{"type":26,"tag":145,"props":2302,"children":2303},{"class":147,"line":270},[2304],{"type":26,"tag":145,"props":2305,"children":2306},{"emptyLinePlaceholder":180},[2307],{"type":31,"value":183},{"type":26,"tag":145,"props":2309,"children":2310},{"class":147,"line":759},[2311,2315,2319],{"type":26,"tag":145,"props":2312,"children":2313},{"style":162},[2314],{"type":31,"value":2134},{"type":26,"tag":145,"props":2316,"children":2317},{"style":2137},[2318],{"type":31,"value":991},{"type":26,"tag":145,"props":2320,"children":2321},{"style":162},[2322],{"type":31,"value":2150},{"type":26,"tag":145,"props":2324,"children":2325},{"class":147,"line":767},[2326,2330],{"type":26,"tag":145,"props":2327,"children":2328},{"style":474},[2329],{"type":31,"value":2091},{"type":26,"tag":145,"props":2331,"children":2332},{"style":162},[2333],{"type":31,"value":2334}," {\n",{"type":26,"tag":145,"props":2336,"children":2337},{"class":147,"line":785},[2338,2343,2347,2352],{"type":26,"tag":145,"props":2339,"children":2340},{"style":650},[2341],{"type":31,"value":2342},"  font-family",{"type":26,"tag":145,"props":2344,"children":2345},{"style":162},[2346],{"type":31,"value":1548},{"type":26,"tag":145,"props":2348,"children":2349},{"style":604},[2350],{"type":31,"value":2351},"'Inter'",{"type":26,"tag":145,"props":2353,"children":2354},{"style":162},[2355],{"type":31,"value":1363},{"type":26,"tag":145,"props":2357,"children":2359},{"class":147,"line":2358},19,[2360,2365,2369,2374,2378,2382,2387,2392,2396,2401],{"type":26,"tag":145,"props":2361,"children":2362},{"style":650},[2363],{"type":31,"value":2364},"  src",{"type":26,"tag":145,"props":2366,"children":2367},{"style":162},[2368],{"type":31,"value":1548},{"type":26,"tag":145,"props":2370,"children":2371},{"style":650},[2372],{"type":31,"value":2373},"url",{"type":26,"tag":145,"props":2375,"children":2376},{"style":162},[2377],{"type":31,"value":796},{"type":26,"tag":145,"props":2379,"children":2380},{"style":604},[2381],{"type":31,"value":2209},{"type":26,"tag":145,"props":2383,"children":2384},{"style":162},[2385],{"type":31,"value":2386},") ",{"type":26,"tag":145,"props":2388,"children":2389},{"style":650},[2390],{"type":31,"value":2391},"format",{"type":26,"tag":145,"props":2393,"children":2394},{"style":162},[2395],{"type":31,"value":796},{"type":26,"tag":145,"props":2397,"children":2398},{"style":604},[2399],{"type":31,"value":2400},"'woff2'",{"type":26,"tag":145,"props":2402,"children":2403},{"style":162},[2404],{"type":31,"value":2405},");\n",{"type":26,"tag":145,"props":2407,"children":2409},{"class":147,"line":2408},20,[2410,2415,2419,2424],{"type":26,"tag":145,"props":2411,"children":2412},{"style":650},[2413],{"type":31,"value":2414},"  font-display",{"type":26,"tag":145,"props":2416,"children":2417},{"style":162},[2418],{"type":31,"value":1548},{"type":26,"tag":145,"props":2420,"children":2421},{"style":650},[2422],{"type":31,"value":2423},"swap",{"type":26,"tag":145,"props":2425,"children":2426},{"style":162},[2427],{"type":31,"value":1363},{"type":26,"tag":145,"props":2429,"children":2431},{"class":147,"line":2430},21,[2432,2437,2441,2446,2451],{"type":26,"tag":145,"props":2433,"children":2434},{"style":650},[2435],{"type":31,"value":2436},"  font-weight",{"type":26,"tag":145,"props":2438,"children":2439},{"style":162},[2440],{"type":31,"value":1548},{"type":26,"tag":145,"props":2442,"children":2443},{"style":650},[2444],{"type":31,"value":2445},"100",{"type":26,"tag":145,"props":2447,"children":2448},{"style":650},[2449],{"type":31,"value":2450}," 900",{"type":26,"tag":145,"props":2452,"children":2453},{"style":162},[2454],{"type":31,"value":1363},{"type":26,"tag":145,"props":2456,"children":2458},{"class":147,"line":2457},22,[2459],{"type":26,"tag":145,"props":2460,"children":2461},{"style":162},[2462],{"type":31,"value":1624},{"type":26,"tag":145,"props":2464,"children":2466},{"class":147,"line":2465},23,[2467,2471,2475],{"type":26,"tag":145,"props":2468,"children":2469},{"style":162},[2470],{"type":31,"value":2292},{"type":26,"tag":145,"props":2472,"children":2473},{"style":2137},[2474],{"type":31,"value":991},{"type":26,"tag":145,"props":2476,"children":2477},{"style":162},[2478],{"type":31,"value":2150},{"type":26,"tag":27,"props":2480,"children":2481},{},[2482,2487,2489,2494],{"type":26,"tag":34,"props":2483,"children":2484},{},[2485],{"type":31,"value":2486},"Gain:",{"type":31,"value":2488}," LCP 10.2s → 7.8s (2.4s drop). Font loading shifts from render-blocking to non-blocking; FOIT (Flash of Invisible Text) duration 1200ms → 180ms. ",{"type":26,"tag":34,"props":2490,"children":2491},{},[2492],{"type":31,"value":2493},"Tradeoff:",{"type":31,"value":2495}," font files now live in your own CDN, version management is manual (we solved this with Cloudflare R2 bucket + Cache-Control headers).",{"type":26,"tag":42,"props":2497,"children":2499},{"id":2498},"selective-hydration-content-visibility",[2500,2502],{"type":31,"value":2501},"Selective hydration + ",{"type":26,"tag":101,"props":2503,"children":2505},{"className":2504},[],[2506],{"type":31,"value":2507},"content-visibility",{"type":26,"tag":27,"props":2509,"children":2510},{},[2511,2513,2519,2521,2527],{"type":31,"value":2512},"Nuxt 3's default hydrates every component. But components below the fold (footer, comments, related products) don't need to hydrate before the user scrolls. We wrapped below-fold components with ",{"type":26,"tag":101,"props":2514,"children":2516},{"className":2515},[],[2517],{"type":31,"value":2518},"LazyHydrate",{"type":31,"value":2520}," from ",{"type":26,"tag":101,"props":2522,"children":2524},{"className":2523},[],[2525],{"type":31,"value":2526},"@nuxt\u002Flazy-hydration",{"type":31,"value":1191},{"type":26,"tag":135,"props":2529,"children":2531},{"className":2112,"code":2530,"language":2114,"meta":9,"style":9},"\u003Ctemplate>\n  \u003CLazyHydrate when-visible>\n    \u003CProductRecommendations :product-id=\"productId\" \u002F>\n  \u003C\u002FLazyHydrate>\n\u003C\u002Ftemplate>\n",[2532],{"type":26,"tag":101,"props":2533,"children":2534},{"__ignoreMap":9},[2535,2551,2572,2604,2620],{"type":26,"tag":145,"props":2536,"children":2537},{"class":147,"line":148},[2538,2542,2547],{"type":26,"tag":145,"props":2539,"children":2540},{"style":162},[2541],{"type":31,"value":2134},{"type":26,"tag":145,"props":2543,"children":2544},{"style":2137},[2545],{"type":31,"value":2546},"template",{"type":26,"tag":145,"props":2548,"children":2549},{"style":162},[2550],{"type":31,"value":2150},{"type":26,"tag":145,"props":2552,"children":2553},{"class":147,"line":158},[2554,2559,2563,2568],{"type":26,"tag":145,"props":2555,"children":2556},{"style":162},[2557],{"type":31,"value":2558},"  \u003C",{"type":26,"tag":145,"props":2560,"children":2561},{"style":2137},[2562],{"type":31,"value":2518},{"type":26,"tag":145,"props":2564,"children":2565},{"style":522},[2566],{"type":31,"value":2567}," when-visible",{"type":26,"tag":145,"props":2569,"children":2570},{"style":162},[2571],{"type":31,"value":2150},{"type":26,"tag":145,"props":2573,"children":2574},{"class":147,"line":168},[2575,2580,2585,2590,2594,2599],{"type":26,"tag":145,"props":2576,"children":2577},{"style":162},[2578],{"type":31,"value":2579},"    \u003C",{"type":26,"tag":145,"props":2581,"children":2582},{"style":2137},[2583],{"type":31,"value":2584},"ProductRecommendations",{"type":26,"tag":145,"props":2586,"children":2587},{"style":522},[2588],{"type":31,"value":2589}," :product-id",{"type":26,"tag":145,"props":2591,"children":2592},{"style":162},[2593],{"type":31,"value":583},{"type":26,"tag":145,"props":2595,"children":2596},{"style":604},[2597],{"type":31,"value":2598},"\"productId\"",{"type":26,"tag":145,"props":2600,"children":2601},{"style":162},[2602],{"type":31,"value":2603}," \u002F>\n",{"type":26,"tag":145,"props":2605,"children":2606},{"class":147,"line":176},[2607,2612,2616],{"type":26,"tag":145,"props":2608,"children":2609},{"style":162},[2610],{"type":31,"value":2611},"  \u003C\u002F",{"type":26,"tag":145,"props":2613,"children":2614},{"style":2137},[2615],{"type":31,"value":2518},{"type":26,"tag":145,"props":2617,"children":2618},{"style":162},[2619],{"type":31,"value":2150},{"type":26,"tag":145,"props":2621,"children":2622},{"class":147,"line":186},[2623,2627,2631],{"type":26,"tag":145,"props":2624,"children":2625},{"style":162},[2626],{"type":31,"value":2292},{"type":26,"tag":145,"props":2628,"children":2629},{"style":2137},[2630],{"type":31,"value":2546},{"type":26,"tag":145,"props":2632,"children":2633},{"style":162},[2634],{"type":31,"value":2150},{"type":26,"tag":27,"props":2636,"children":2637},{},[2638,2640,2646],{"type":31,"value":2639},"On the CSS side, ",{"type":26,"tag":101,"props":2641,"children":2643},{"className":2642},[],[2644],{"type":31,"value":2645},"content-visibility: auto",{"type":31,"value":2647}," signals the browser: \"skip rendering this element if it's not in the viewport.\"",{"type":26,"tag":135,"props":2649,"children":2653},{"className":2650,"code":2651,"language":2652,"meta":9,"style":9},"language-css shiki shiki-themes github-dark",".product-recommendations {\n  content-visibility: auto;\n  contain-intrinsic-size: 0 500px; \u002F* placeholder height *\u002F\n}\n","css",[2654],{"type":26,"tag":101,"props":2655,"children":2656},{"__ignoreMap":9},[2657,2669,2690,2726],{"type":26,"tag":145,"props":2658,"children":2659},{"class":147,"line":148},[2660,2665],{"type":26,"tag":145,"props":2661,"children":2662},{"style":522},[2663],{"type":31,"value":2664},".product-recommendations",{"type":26,"tag":145,"props":2666,"children":2667},{"style":162},[2668],{"type":31,"value":2334},{"type":26,"tag":145,"props":2670,"children":2671},{"class":147,"line":158},[2672,2677,2681,2686],{"type":26,"tag":145,"props":2673,"children":2674},{"style":650},[2675],{"type":31,"value":2676},"  content-visibility",{"type":26,"tag":145,"props":2678,"children":2679},{"style":162},[2680],{"type":31,"value":1548},{"type":26,"tag":145,"props":2682,"children":2683},{"style":650},[2684],{"type":31,"value":2685},"auto",{"type":26,"tag":145,"props":2687,"children":2688},{"style":162},[2689],{"type":31,"value":1363},{"type":26,"tag":145,"props":2691,"children":2692},{"class":147,"line":168},[2693,2698,2702,2706,2711,2716,2721],{"type":26,"tag":145,"props":2694,"children":2695},{"style":650},[2696],{"type":31,"value":2697},"  contain-intrinsic-size",{"type":26,"tag":145,"props":2699,"children":2700},{"style":162},[2701],{"type":31,"value":1548},{"type":26,"tag":145,"props":2703,"children":2704},{"style":650},[2705],{"type":31,"value":653},{"type":26,"tag":145,"props":2707,"children":2708},{"style":650},[2709],{"type":31,"value":2710}," 500",{"type":26,"tag":145,"props":2712,"children":2713},{"style":474},[2714],{"type":31,"value":2715},"px",{"type":26,"tag":145,"props":2717,"children":2718},{"style":162},[2719],{"type":31,"value":2720},"; ",{"type":26,"tag":145,"props":2722,"children":2723},{"style":1332},[2724],{"type":31,"value":2725},"\u002F* placeholder height *\u002F\n",{"type":26,"tag":145,"props":2727,"children":2728},{"class":147,"line":176},[2729],{"type":26,"tag":145,"props":2730,"children":2731},{"style":162},[2732],{"type":31,"value":1624},{"type":26,"tag":27,"props":2734,"children":2735},{},[2736,2740,2742,2746,2747,2753],{"type":26,"tag":34,"props":2737,"children":2738},{},[2739],{"type":31,"value":2486},{"type":31,"value":2741}," TBT 2190ms → 420ms, LCP 7.8s → 4.1s. Initial JS bundle 420kB → 180kB (brotli-compressed). ",{"type":26,"tag":34,"props":2743,"children":2744},{},[2745],{"type":31,"value":2493},{"type":31,"value":1157},{"type":26,"tag":101,"props":2748,"children":2750},{"className":2749},[],[2751],{"type":31,"value":2752},"when-visible",{"type":31,"value":2754}," uses Intersection Observer; old browsers like IE11 need polyfills (not a concern for us since we target modern browsers).",{"type":26,"tag":42,"props":2756,"children":2758},{"id":2757},"edge-caching-isr-hybrid-approach",[2759],{"type":31,"value":2760},"Edge caching + ISR hybrid approach",{"type":26,"tag":27,"props":2762,"children":2763},{},[2764,2766,2772,2774,2780],{"type":31,"value":2765},"Cloudflare Pages caches static assets by default but doesn't cache SSR endpoints (outside ",{"type":26,"tag":101,"props":2767,"children":2769},{"className":2768},[],[2770],{"type":31,"value":2771},"\u002F_nuxt\u002F...",{"type":31,"value":2773},"). We defined route-specific cache rules in ",{"type":26,"tag":101,"props":2775,"children":2777},{"className":2776},[],[2778],{"type":31,"value":2779},"nuxt.config.ts",{"type":31,"value":2781},":",{"type":26,"tag":135,"props":2783,"children":2787},{"className":2784,"code":2785,"language":2786,"meta":9,"style":9},"language-ts shiki shiki-themes github-dark","\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  routeRules: {\n    '\u002F': { swr: 3600 }, \u002F\u002F homepage 1h stale-while-revalidate\n    '\u002Fproduct\u002F**': { swr: 1800 }, \u002F\u002F product pages 30m\n    '\u002Fcategory\u002F**': { static: true } \u002F\u002F category pages build-time static\n  }\n})\n","ts",[2788],{"type":26,"tag":101,"props":2789,"children":2790},{"__ignoreMap":9},[2791,2799,2821,2829,2857,2883,2911,2919],{"type":26,"tag":145,"props":2792,"children":2793},{"class":147,"line":148},[2794],{"type":26,"tag":145,"props":2795,"children":2796},{"style":1332},[2797],{"type":31,"value":2798},"\u002F\u002F nuxt.config.ts\n",{"type":26,"tag":145,"props":2800,"children":2801},{"class":147,"line":158},[2802,2807,2812,2817],{"type":26,"tag":145,"props":2803,"children":2804},{"style":474},[2805],{"type":31,"value":2806},"export",{"type":26,"tag":145,"props":2808,"children":2809},{"style":474},[2810],{"type":31,"value":2811}," default",{"type":26,"tag":145,"props":2813,"children":2814},{"style":522},[2815],{"type":31,"value":2816}," defineNuxtConfig",{"type":26,"tag":145,"props":2818,"children":2819},{"style":162},[2820],{"type":31,"value":2163},{"type":26,"tag":145,"props":2822,"children":2823},{"class":147,"line":168},[2824],{"type":26,"tag":145,"props":2825,"children":2826},{"style":162},[2827],{"type":31,"value":2828},"  routeRules: {\n",{"type":26,"tag":145,"props":2830,"children":2831},{"class":147,"line":176},[2832,2837,2842,2847,2852],{"type":26,"tag":145,"props":2833,"children":2834},{"style":604},[2835],{"type":31,"value":2836},"    '\u002F'",{"type":26,"tag":145,"props":2838,"children":2839},{"style":162},[2840],{"type":31,"value":2841},": { swr: ",{"type":26,"tag":145,"props":2843,"children":2844},{"style":650},[2845],{"type":31,"value":2846},"3600",{"type":26,"tag":145,"props":2848,"children":2849},{"style":162},[2850],{"type":31,"value":2851}," }, ",{"type":26,"tag":145,"props":2853,"children":2854},{"style":1332},[2855],{"type":31,"value":2856},"\u002F\u002F homepage 1h stale-while-revalidate\n",{"type":26,"tag":145,"props":2858,"children":2859},{"class":147,"line":186},[2860,2865,2869,2874,2878],{"type":26,"tag":145,"props":2861,"children":2862},{"style":604},[2863],{"type":31,"value":2864},"    '\u002Fproduct\u002F**'",{"type":26,"tag":145,"props":2866,"children":2867},{"style":162},[2868],{"type":31,"value":2841},{"type":26,"tag":145,"props":2870,"children":2871},{"style":650},[2872],{"type":31,"value":2873},"1800",{"type":26,"tag":145,"props":2875,"children":2876},{"style":162},[2877],{"type":31,"value":2851},{"type":26,"tag":145,"props":2879,"children":2880},{"style":1332},[2881],{"type":31,"value":2882},"\u002F\u002F product pages 30m\n",{"type":26,"tag":145,"props":2884,"children":2885},{"class":147,"line":195},[2886,2891,2896,2901,2906],{"type":26,"tag":145,"props":2887,"children":2888},{"style":604},[2889],{"type":31,"value":2890},"    '\u002Fcategory\u002F**'",{"type":26,"tag":145,"props":2892,"children":2893},{"style":162},[2894],{"type":31,"value":2895},": { static: ",{"type":26,"tag":145,"props":2897,"children":2898},{"style":650},[2899],{"type":31,"value":2900},"true",{"type":26,"tag":145,"props":2902,"children":2903},{"style":162},[2904],{"type":31,"value":2905}," } ",{"type":26,"tag":145,"props":2907,"children":2908},{"style":1332},[2909],{"type":31,"value":2910},"\u002F\u002F category pages build-time static\n",{"type":26,"tag":145,"props":2912,"children":2913},{"class":147,"line":203},[2914],{"type":26,"tag":145,"props":2915,"children":2916},{"style":162},[2917],{"type":31,"value":2918},"  }\n",{"type":26,"tag":145,"props":2920,"children":2921},{"class":147,"line":20},[2922],{"type":26,"tag":145,"props":2923,"children":2924},{"style":162},[2925],{"type":31,"value":2284},{"type":26,"tag":27,"props":2927,"children":2928},{},[2929,2934],{"type":26,"tag":34,"props":2930,"children":2931},{},[2932],{"type":31,"value":2933},"SWR strategy:",{"type":31,"value":2935}," the first request SSR-renders; subsequent requests serve from cache; the background re-renders silently. We used URL + user segment (logged-in\u002Fanonymous) as the cache key in Cloudflare KV.",{"type":26,"tag":27,"props":2937,"children":2938},{},[2939,2943,2945,2949],{"type":26,"tag":34,"props":2940,"children":2941},{},[2942],{"type":31,"value":2486},{"type":31,"value":2944}," TTFB (Time to First Byte) 840ms → 120ms, LCP 4.1s → 2.3s. Cache hit rate reached 78% in week one. ",{"type":26,"tag":34,"props":2946,"children":2947},{},[2948],{"type":31,"value":2493},{"type":31,"value":2950}," personalization binds to the cache key—user-specific data like cart item count can't be cached; we fetch those client-side.",{"type":26,"tag":42,"props":2952,"children":2954},{"id":2953},"above-the-fold-image-optimization",[2955],{"type":31,"value":2956},"Above-the-fold image optimization",{"type":26,"tag":27,"props":2958,"children":2959},{},[2960,2962,2968],{"type":31,"value":2961},"We converted the 1.2MB JPEG hero image to 180kB WebP and added responsive breakpoints with ",{"type":26,"tag":101,"props":2963,"children":2965},{"className":2964},[],[2966],{"type":31,"value":2967},"\u003Cpicture>",{"type":31,"value":2781},{"type":26,"tag":135,"props":2970,"children":2972},{"className":2112,"code":2971,"language":2114,"meta":9,"style":9},"\u003Cpicture>\n  \u003Csource\n    srcset=\"\u002Fimages\u002Fhero-mobile.webp\"\n    media=\"(max-width: 640px)\"\n    type=\"image\u002Fwebp\"\n  \u002F>\n  \u003Csource\n    srcset=\"\u002Fimages\u002Fhero-desktop.webp\"\n    media=\"(min-width: 641px)\"\n    type=\"image\u002Fwebp\"\n  \u002F>\n  \u003Cimg\n    src=\"\u002Fimages\u002Fhero-desktop.jpg\"\n    alt=\"New season collection\"\n    fetchpriority=\"high\"\n    decoding=\"async\"\n  \u002F>\n\u003C\u002Fpicture>\n",[2973],{"type":26,"tag":101,"props":2974,"children":2975},{"__ignoreMap":9},[2976,2992,3000,3008,3016,3024,3032,3039,3047,3055,3062,3069,3077,3085,3093,3101,3109,3116],{"type":26,"tag":145,"props":2977,"children":2978},{"class":147,"line":148},[2979,2983,2988],{"type":26,"tag":145,"props":2980,"children":2981},{"style":162},[2982],{"type":31,"value":2134},{"type":26,"tag":145,"props":2984,"children":2985},{"style":2137},[2986],{"type":31,"value":2987},"picture",{"type":26,"tag":145,"props":2989,"children":2990},{"style":162},[2991],{"type":31,"value":2150},{"type":26,"tag":145,"props":2993,"children":2994},{"class":147,"line":158},[2995],{"type":26,"tag":145,"props":2996,"children":2997},{"style":162},[2998],{"type":31,"value":2999},"  \u003Csource\n",{"type":26,"tag":145,"props":3001,"children":3002},{"class":147,"line":168},[3003],{"type":26,"tag":145,"props":3004,"children":3005},{"style":162},[3006],{"type":31,"value":3007},"    srcset=\"\u002Fimages\u002Fhero-mobile.webp\"\n",{"type":26,"tag":145,"props":3009,"children":3010},{"class":147,"line":176},[3011],{"type":26,"tag":145,"props":3012,"children":3013},{"style":162},[3014],{"type":31,"value":3015},"    media=\"(max-width: 640px)\"\n",{"type":26,"tag":145,"props":3017,"children":3018},{"class":147,"line":186},[3019],{"type":26,"tag":145,"props":3020,"children":3021},{"style":162},[3022],{"type":31,"value":3023},"    type=\"image\u002Fwebp\"\n",{"type":26,"tag":145,"props":3025,"children":3026},{"class":147,"line":195},[3027],{"type":26,"tag":145,"props":3028,"children":3029},{"style":162},[3030],{"type":31,"value":3031},"  \u002F>\n",{"type":26,"tag":145,"props":3033,"children":3034},{"class":147,"line":203},[3035],{"type":26,"tag":145,"props":3036,"children":3037},{"style":162},[3038],{"type":31,"value":2999},{"type":26,"tag":145,"props":3040,"children":3041},{"class":147,"line":20},[3042],{"type":26,"tag":145,"props":3043,"children":3044},{"style":162},[3045],{"type":31,"value":3046},"    srcset=\"\u002Fimages\u002Fhero-desktop.webp\"\n",{"type":26,"tag":145,"props":3048,"children":3049},{"class":147,"line":219},[3050],{"type":26,"tag":145,"props":3051,"children":3052},{"style":162},[3053],{"type":31,"value":3054},"    media=\"(min-width: 641px)\"\n",{"type":26,"tag":145,"props":3056,"children":3057},{"class":147,"line":228},[3058],{"type":26,"tag":145,"props":3059,"children":3060},{"style":162},[3061],{"type":31,"value":3023},{"type":26,"tag":145,"props":3063,"children":3064},{"class":147,"line":236},[3065],{"type":26,"tag":145,"props":3066,"children":3067},{"style":162},[3068],{"type":31,"value":3031},{"type":26,"tag":145,"props":3070,"children":3071},{"class":147,"line":245},[3072],{"type":26,"tag":145,"props":3073,"children":3074},{"style":162},[3075],{"type":31,"value":3076},"  \u003Cimg\n",{"type":26,"tag":145,"props":3078,"children":3079},{"class":147,"line":253},[3080],{"type":26,"tag":145,"props":3081,"children":3082},{"style":162},[3083],{"type":31,"value":3084},"    src=\"\u002Fimages\u002Fhero-desktop.jpg\"\n",{"type":26,"tag":145,"props":3086,"children":3087},{"class":147,"line":262},[3088],{"type":26,"tag":145,"props":3089,"children":3090},{"style":162},[3091],{"type":31,"value":3092},"    alt=\"New season collection\"\n",{"type":26,"tag":145,"props":3094,"children":3095},{"class":147,"line":270},[3096],{"type":26,"tag":145,"props":3097,"children":3098},{"style":162},[3099],{"type":31,"value":3100},"    fetchpriority=\"high\"\n",{"type":26,"tag":145,"props":3102,"children":3103},{"class":147,"line":759},[3104],{"type":26,"tag":145,"props":3105,"children":3106},{"style":162},[3107],{"type":31,"value":3108},"    decoding=\"async\"\n",{"type":26,"tag":145,"props":3110,"children":3111},{"class":147,"line":767},[3112],{"type":26,"tag":145,"props":3113,"children":3114},{"style":162},[3115],{"type":31,"value":3031},{"type":26,"tag":145,"props":3117,"children":3118},{"class":147,"line":785},[3119,3123,3127],{"type":26,"tag":145,"props":3120,"children":3121},{"style":162},[3122],{"type":31,"value":2292},{"type":26,"tag":145,"props":3124,"children":3125},{"style":2137},[3126],{"type":31,"value":2987},{"type":26,"tag":145,"props":3128,"children":3129},{"style":162},[3130],{"type":31,"value":2150},{"type":26,"tag":27,"props":3132,"children":3133},{},[3134,3136,3142],{"type":31,"value":3135},"The ",{"type":26,"tag":101,"props":3137,"children":3139},{"className":3138},[],[3140],{"type":31,"value":3141},"fetchpriority=\"high\"",{"type":31,"value":3143}," attribute signals to the browser: \"load this image first.\" Cloudflare Image Resizing automatically converts formats at the edge (serving JPEG to browsers without WebP support).",{"type":26,"tag":27,"props":3145,"children":3146},{},[3147,3151,3153,3159],{"type":26,"tag":34,"props":3148,"children":3149},{},[3150],{"type":31,"value":2486},{"type":31,"value":3152}," LCP 2.3s → 2.1s, image load time 1200ms → 320ms. CLS (Cumulative Layout Shift) 0.12 → 0.02—we reserved placeholder space with the ",{"type":26,"tag":101,"props":3154,"children":3156},{"className":3155},[],[3157],{"type":31,"value":3158},"aspect-ratio",{"type":31,"value":3160}," CSS property.",{"type":26,"tag":42,"props":3162,"children":3164},{"id":3163},"benchmark-results-real-user-impact",[3165],{"type":31,"value":3166},"Benchmark results + real-user impact",{"type":26,"tag":27,"props":3168,"children":3169},{},[3170],{"type":31,"value":3171},"PageSpeed Insights mobile score 34 → 92, desktop 62 → 98. 28-day CrUX averages:",{"type":26,"tag":3173,"props":3174,"children":3175},"table",{},[3176,3205],{"type":26,"tag":3177,"props":3178,"children":3179},"thead",{},[3180],{"type":26,"tag":3181,"props":3182,"children":3183},"tr",{},[3184,3190,3195,3200],{"type":26,"tag":3185,"props":3186,"children":3187},"th",{},[3188],{"type":31,"value":3189},"Metric",{"type":26,"tag":3185,"props":3191,"children":3192},{},[3193],{"type":31,"value":3194},"Before",{"type":26,"tag":3185,"props":3196,"children":3197},{},[3198],{"type":31,"value":3199},"After",{"type":26,"tag":3185,"props":3201,"children":3202},{},[3203],{"type":31,"value":3204},"Change",{"type":26,"tag":3206,"props":3207,"children":3208},"tbody",{},[3209,3233,3256,3279],{"type":26,"tag":3181,"props":3210,"children":3211},{},[3212,3218,3223,3228],{"type":26,"tag":3213,"props":3214,"children":3215},"td",{},[3216],{"type":31,"value":3217},"LCP",{"type":26,"tag":3213,"props":3219,"children":3220},{},[3221],{"type":31,"value":3222},"10.2s",{"type":26,"tag":3213,"props":3224,"children":3225},{},[3226],{"type":31,"value":3227},"2.1s",{"type":26,"tag":3213,"props":3229,"children":3230},{},[3231],{"type":31,"value":3232},"−79%",{"type":26,"tag":3181,"props":3234,"children":3235},{},[3236,3241,3246,3251],{"type":26,"tag":3213,"props":3237,"children":3238},{},[3239],{"type":31,"value":3240},"TBT",{"type":26,"tag":3213,"props":3242,"children":3243},{},[3244],{"type":31,"value":3245},"2190ms",{"type":26,"tag":3213,"props":3247,"children":3248},{},[3249],{"type":31,"value":3250},"420ms",{"type":26,"tag":3213,"props":3252,"children":3253},{},[3254],{"type":31,"value":3255},"−81%",{"type":26,"tag":3181,"props":3257,"children":3258},{},[3259,3264,3269,3274],{"type":26,"tag":3213,"props":3260,"children":3261},{},[3262],{"type":31,"value":3263},"CLS",{"type":26,"tag":3213,"props":3265,"children":3266},{},[3267],{"type":31,"value":3268},"0.12",{"type":26,"tag":3213,"props":3270,"children":3271},{},[3272],{"type":31,"value":3273},"0.02",{"type":26,"tag":3213,"props":3275,"children":3276},{},[3277],{"type":31,"value":3278},"−83%",{"type":26,"tag":3181,"props":3280,"children":3281},{},[3282,3287,3292,3297],{"type":26,"tag":3213,"props":3283,"children":3284},{},[3285],{"type":31,"value":3286},"TTFB",{"type":26,"tag":3213,"props":3288,"children":3289},{},[3290],{"type":31,"value":3291},"840ms",{"type":26,"tag":3213,"props":3293,"children":3294},{},[3295],{"type":31,"value":3296},"120ms",{"type":26,"tag":3213,"props":3298,"children":3299},{},[3300],{"type":31,"value":3301},"−86%",{"type":26,"tag":27,"props":3303,"children":3304},{},[3305,3307,3314],{"type":31,"value":3306},"Google Analytics checkout funnel: checkout initiation rate 3.2% → 4.8% (+50% relative lift). Bounce rate 68% → 52%. Search Console: organic traffic grew 34% over 2 months (other SEO changes held constant). These numbers align with Roibase's ",{"type":26,"tag":326,"props":3308,"children":3311},{"href":3309,"rel":3310},"https:\u002F\u002Fwww.roibase.com.tr\u002Fen\u002Fheadless",[330],[3312],{"type":31,"value":3313},"Headless",{"type":31,"value":3315}," standards—if performance doesn't drive business metrics, the architecture change isn't successful.",{"type":26,"tag":42,"props":3317,"children":3319},{"id":3318},"tradeoffs-and-decision-criteria",[3320],{"type":31,"value":3321},"Tradeoffs and decision criteria",{"type":26,"tag":27,"props":3323,"children":3324},{},[3325,3330,3332,3337,3339,3344,3345,3351],{"type":26,"tag":34,"props":3326,"children":3327},{},[3328],{"type":31,"value":3329},"Developer experience:",{"type":31,"value":3331}," wrapping components in ",{"type":26,"tag":101,"props":3333,"children":3335},{"className":3334},[],[3336],{"type":31,"value":2518},{"type":31,"value":3338}," expands the API surface; new developers must learn the difference between ",{"type":26,"tag":101,"props":3340,"children":3342},{"className":3341},[],[3343],{"type":31,"value":2752},{"type":31,"value":403},{"type":26,"tag":101,"props":3346,"children":3348},{"className":3347},[],[3349],{"type":31,"value":3350},"when-idle",{"type":31,"value":3352},". We addressed this with Storybook documentation + ESLint rules.",{"type":26,"tag":27,"props":3354,"children":3355},{},[3356,3361],{"type":26,"tag":34,"props":3357,"children":3358},{},[3359],{"type":31,"value":3360},"Bundle size vs. runtime cost:",{"type":31,"value":3362}," self-hosted fonts add ~60kB to the initial bundle but eliminate DNS lookup + TLS handshake overhead. This tradeoff pays off on mobile 3G networks and is neutral on fiber.",{"type":26,"tag":27,"props":3364,"children":3365},{},[3366,3371],{"type":26,"tag":34,"props":3367,"children":3368},{},[3369],{"type":31,"value":3370},"Cache invalidation:",{"type":31,"value":3372}," SWR carries stale-data risk. We handle critical data (inventory) with client-side real-time fetches using 30-second polling instead of WebSocket—lower edge function costs.",{"type":26,"tag":27,"props":3374,"children":3375},{},[3376,3381,3382,3388],{"type":26,"tag":34,"props":3377,"children":3378},{},[3379],{"type":31,"value":3380},"Cloudflare vendor lock-in:",{"type":31,"value":1157},{"type":26,"tag":101,"props":3383,"children":3385},{"className":3384},[],[3386],{"type":31,"value":3387},"routeRules",{"type":31,"value":3389}," caching is Cloudflare-specific; porting to another platform requires re-implementation. But Vercel and Netlify offer equivalent primitives; migration effort is acceptable.",{"type":26,"tag":42,"props":3391,"children":3393},{"id":3392},"next-steps",[3394],{"type":31,"value":3395},"Next steps",{"type":26,"tag":27,"props":3397,"children":3398},{},[3399],{"type":31,"value":3400},"2.1s LCP is solid, but CrUX P75 (75th percentile) still sits at 3.2s. Our roadmap:",{"type":26,"tag":412,"props":3402,"children":3403},{},[3404,3414,3424,3434],{"type":26,"tag":416,"props":3405,"children":3406},{},[3407,3412],{"type":26,"tag":34,"props":3408,"children":3409},{},[3410],{"type":31,"value":3411},"Image CDN + automatic format negotiation:",{"type":31,"value":3413}," Imgix instead of Cloudflare Polish, AVIF support",{"type":26,"tag":416,"props":3415,"children":3416},{},[3417,3422],{"type":26,"tag":34,"props":3418,"children":3419},{},[3420],{"type":31,"value":3421},"Prefetch strategy:",{"type":31,"value":3423}," Intersection Observer to prefetch data for product cards approaching the viewport",{"type":26,"tag":416,"props":3425,"children":3426},{},[3427,3432],{"type":26,"tag":34,"props":3428,"children":3429},{},[3430],{"type":31,"value":3431},"Service Worker + offline-first:",{"type":31,"value":3433}," Workbox for critical asset caching, network-first fallback",{"type":26,"tag":416,"props":3435,"children":3436},{},[3437,3442],{"type":26,"tag":34,"props":3438,"children":3439},{},[3440],{"type":31,"value":3441},"Aggressive bundle splitting:",{"type":31,"value":3443}," Nuxt 3's code splitting with route-based chunking",{"type":26,"tag":27,"props":3445,"children":3446},{},[3447],{"type":31,"value":3448},"Performance optimization is an endless game—every 100ms gain delivers 1–2% conversion lift. Nuxt 3 + Cloudflare Pages balances edge rendering with modern JS framework ergonomics. When choosing a stack, define LCP targets as business requirements, then evaluate architectural options within that constraint.",{"type":26,"tag":991,"props":3450,"children":3451},{},[3452],{"type":31,"value":995},{"title":9,"searchDepth":168,"depth":168,"links":3454},[3455,3456,3457,3459,3460,3461,3462,3463],{"id":2009,"depth":158,"text":2012},{"id":2069,"depth":158,"text":2072},{"id":2498,"depth":158,"text":3458},"Selective hydration + content-visibility",{"id":2757,"depth":158,"text":2760},{"id":2953,"depth":158,"text":2956},{"id":3163,"depth":158,"text":3166},{"id":3318,"depth":158,"text":3321},{"id":3392,"depth":158,"text":3395},"content:en:tech:nuxt-3-cloudflare-pages-lcp-optimization.md","en\u002Ftech\u002Fnuxt-3-cloudflare-pages-lcp-optimization.md","en\u002Ftech\u002Fnuxt-3-cloudflare-pages-lcp-optimization",{"ai":148,"marketing":148,"tech":148,"data":3468,"gaming":3468,"travel":3468,"lifestyle":3468},0,1778164175036]