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