[{"data":1,"prerenderedAt":1963},["ShallowReactive",2],{"header-latest":3,"post-\u002Fblog\u002Fgenerative-engine-optimization-geo":1372},[4],{"id":5,"title":6,"body":7,"date":1346,"description":1347,"extension":1348,"faq":1349,"image":1359,"lang":1360,"meta":1361,"navigation":108,"path":1362,"published":108,"readTime":215,"seo":1363,"stem":1364,"tags":1365,"updated":1346,"__hash__":1371},"blog\u002Fblog\u002Fen\u002Ftelegram-web-apps-sells.md","Telegram Web Apps (TWA): How to Launch a Full SaaS Inside Telegram",{"type":8,"value":9,"toc":1335},"minimark",[10,19,22,25,30,33,44,52,63,70,73,856,860,863,868,875,923,927,930,1215,1219,1229,1232,1270,1283,1291,1295,1315,1318,1331],[11,12,13,14,18],"p",{},"Telegram has transcended its origins as a privacy-focused messaging client to become a powerful, cross-platform runtime environment. The introduction of ",[15,16,17],"strong",{},"Telegram Web Apps (TWA)",", officially known as Telegram Mini Apps, allows developers to build highly interactive single-page applications (SPAs) that load directly inside the Telegram application shell.",[11,20,21],{},"This provides startups and enterprises with immediate, frictionless access to over 900 million active users. By embedding your B2B SaaS, CRM interface, or utility tool inside a Telegram bot, you remove the classic conversion hurdles of app store downloads, desktop logins, and sign-up flows.",[11,23,24],{},"In this developer guide, we will analyze the technical architecture of a TWA, implement a secure hash verification check on the backend, and look at frontend integration patterns.",[26,27,29],"h2",{"id":28},"the-telegram-mini-app-ecosystem-architecture","The Telegram Mini App Ecosystem Architecture",[11,31,32],{},"Unlike traditional web applications, a TWA has a dual parent relationship. The frontend runs in a sandboxed browser component (WebView) controlled by the Telegram client app, while the backend speaks both to the Telegram Bot API and your application database.",[34,35,41],"pre",{"className":36,"code":38,"language":39,"meta":40},[37],"language-text","+-----------------------------------------------------------+\n|                      Telegram Client                      |\n|  +-----------------------------------------------------+  |\n|  |                Mini App (WebView UI)                |  |\n|  |     (Uses window.Telegram.WebApp SDK for bridge)    |  |\n|  +--------------------------+--------------------------+  |\n+-----------------------------|-----------------------------+\n       | (initData Query)     | (Secure HTTPS Request)\n       v                      v\n+--------------+       +------------------------------------+\n| Telegram API |       |            Your Backend            |\n|  (Webhooks)  |       |  (Validates initData via HMAC-256) |\n+------+-------+       +-----------------+------------------+\n       |                                 |\n       +----------------> [DB Sync] \u003C----+\n","text","",[42,43,38],"code",{"__ignoreMap":40},[26,45,47,48,51],{"id":46},"_1-security-first-validating-the-initdata-payload","1. Security First: Validating the ",[42,49,50],{},"initData"," Payload",[11,53,54,55,58,59,62],{},"When a user opens your Mini App, Telegram appends a parameter called ",[42,56,57],{},"tgWebAppData"," (or raw search parameters) containing user profiles, launch contexts, and a security ",[42,60,61],{},"hash",".",[11,64,65,66,69],{},"To prevent users from modifying their user IDs or mocking paid subscription privileges, you ",[15,67,68],{},"must validate this hash on your backend"," using your Telegram Bot Token as the HMAC key.",[11,71,72],{},"Here is the cryptographic validation implementation using Node.js:",[34,74,78],{"className":75,"code":76,"language":77,"meta":40,"style":40},"language-typescript shiki shiki-themes github-dark","import crypto from 'crypto';\n\ninterface TelegramUserData {\n  id: number;\n  first_name: string;\n  last_name?: string;\n  username?: string;\n  language_code?: string;\n  is_premium?: boolean;\n}\n\ninterface ValidationResult {\n  isValid: boolean;\n  user?: TelegramUserData;\n}\n\nexport function verifyTelegramInitData(rawQueryString: string, botToken: string): ValidationResult {\n  const urlParams = new URLSearchParams(rawQueryString);\n  const hash = urlParams.get('hash');\n  \n  if (!hash) {\n    return { isValid: false };\n  }\n\n  \u002F\u002F 1. Sort all incoming parameters alphabetically, excluding the hash itself\n  const keys = Array.from(urlParams.keys()).filter(key => key !== 'hash').sort();\n  \n  \u002F\u002F 2. Re-create the verification data-check string\n  const dataCheckString = keys\n    .map(key => `${key}=${urlParams.get(key)}`)\n    .join('\\n');\n\n  \u002F\u002F 3. Generate the secret cryptographic key\n  \u002F\u002F We use the constant string \"WebAppData\" to sign the bot token first\n  const secretKey = crypto\n    .createHmac('sha256', 'WebAppData')\n    .update(botToken)\n    .digest();\n\n  \u002F\u002F 4. Calculate the expected hash of the sorted string\n  const computedHash = crypto\n    .createHmac('sha256', secretKey)\n    .update(dataCheckString)\n    .digest('hex');\n\n  \u002F\u002F 5. Compare computed signature with the signature sent by the client\n  const isValid = computedHash === hash;\n\n  if (!isValid) {\n    return { isValid: false };\n  }\n\n  \u002F\u002F Parse user data object if validation succeeded\n  try {\n    const userRaw = urlParams.get('user');\n    const user: TelegramUserData = userRaw ? JSON.parse(userRaw) : undefined;\n    return { isValid: true, user };\n  } catch (error) {\n    return { isValid: true };\n  }\n}\n","typescript",[42,79,80,103,110,123,139,152,165,177,189,202,208,213,223,235,247,252,257,298,319,343,349,364,379,385,390,397,450,455,461,474,516,536,541,547,553,566,586,597,607,612,618,630,644,654,668,673,679,698,703,715,726,731,736,742,750,772,810,823,835,846,851],{"__ignoreMap":40},[81,82,85,89,93,96,100],"span",{"class":83,"line":84},"line",1,[81,86,88],{"class":87},"snl16","import",[81,90,92],{"class":91},"s95oV"," crypto ",[81,94,95],{"class":87},"from",[81,97,99],{"class":98},"sU2Wk"," 'crypto'",[81,101,102],{"class":91},";\n",[81,104,106],{"class":83,"line":105},2,[81,107,109],{"emptyLinePlaceholder":108},true,"\n",[81,111,113,116,120],{"class":83,"line":112},3,[81,114,115],{"class":87},"interface",[81,117,119],{"class":118},"svObZ"," TelegramUserData",[81,121,122],{"class":91}," {\n",[81,124,126,130,133,137],{"class":83,"line":125},4,[81,127,129],{"class":128},"s9osk","  id",[81,131,132],{"class":87},":",[81,134,136],{"class":135},"sDLfK"," number",[81,138,102],{"class":91},[81,140,142,145,147,150],{"class":83,"line":141},5,[81,143,144],{"class":128},"  first_name",[81,146,132],{"class":87},[81,148,149],{"class":135}," string",[81,151,102],{"class":91},[81,153,155,158,161,163],{"class":83,"line":154},6,[81,156,157],{"class":128},"  last_name",[81,159,160],{"class":87},"?:",[81,162,149],{"class":135},[81,164,102],{"class":91},[81,166,168,171,173,175],{"class":83,"line":167},7,[81,169,170],{"class":128},"  username",[81,172,160],{"class":87},[81,174,149],{"class":135},[81,176,102],{"class":91},[81,178,180,183,185,187],{"class":83,"line":179},8,[81,181,182],{"class":128},"  language_code",[81,184,160],{"class":87},[81,186,149],{"class":135},[81,188,102],{"class":91},[81,190,192,195,197,200],{"class":83,"line":191},9,[81,193,194],{"class":128},"  is_premium",[81,196,160],{"class":87},[81,198,199],{"class":135}," boolean",[81,201,102],{"class":91},[81,203,205],{"class":83,"line":204},10,[81,206,207],{"class":91},"}\n",[81,209,211],{"class":83,"line":210},11,[81,212,109],{"emptyLinePlaceholder":108},[81,214,216,218,221],{"class":83,"line":215},12,[81,217,115],{"class":87},[81,219,220],{"class":118}," ValidationResult",[81,222,122],{"class":91},[81,224,226,229,231,233],{"class":83,"line":225},13,[81,227,228],{"class":128},"  isValid",[81,230,132],{"class":87},[81,232,199],{"class":135},[81,234,102],{"class":91},[81,236,238,241,243,245],{"class":83,"line":237},14,[81,239,240],{"class":128},"  user",[81,242,160],{"class":87},[81,244,119],{"class":118},[81,246,102],{"class":91},[81,248,250],{"class":83,"line":249},15,[81,251,207],{"class":91},[81,253,255],{"class":83,"line":254},16,[81,256,109],{"emptyLinePlaceholder":108},[81,258,260,263,266,269,272,275,277,279,282,285,287,289,292,294,296],{"class":83,"line":259},17,[81,261,262],{"class":87},"export",[81,264,265],{"class":87}," function",[81,267,268],{"class":118}," verifyTelegramInitData",[81,270,271],{"class":91},"(",[81,273,274],{"class":128},"rawQueryString",[81,276,132],{"class":87},[81,278,149],{"class":135},[81,280,281],{"class":91},", ",[81,283,284],{"class":128},"botToken",[81,286,132],{"class":87},[81,288,149],{"class":135},[81,290,291],{"class":91},")",[81,293,132],{"class":87},[81,295,220],{"class":118},[81,297,122],{"class":91},[81,299,301,304,307,310,313,316],{"class":83,"line":300},18,[81,302,303],{"class":87},"  const",[81,305,306],{"class":135}," urlParams",[81,308,309],{"class":87}," =",[81,311,312],{"class":87}," new",[81,314,315],{"class":118}," URLSearchParams",[81,317,318],{"class":91},"(rawQueryString);\n",[81,320,322,324,327,329,332,335,337,340],{"class":83,"line":321},19,[81,323,303],{"class":87},[81,325,326],{"class":135}," hash",[81,328,309],{"class":87},[81,330,331],{"class":91}," urlParams.",[81,333,334],{"class":118},"get",[81,336,271],{"class":91},[81,338,339],{"class":98},"'hash'",[81,341,342],{"class":91},");\n",[81,344,346],{"class":83,"line":345},20,[81,347,348],{"class":91},"  \n",[81,350,352,355,358,361],{"class":83,"line":351},21,[81,353,354],{"class":87},"  if",[81,356,357],{"class":91}," (",[81,359,360],{"class":87},"!",[81,362,363],{"class":91},"hash) {\n",[81,365,367,370,373,376],{"class":83,"line":366},22,[81,368,369],{"class":87},"    return",[81,371,372],{"class":91}," { isValid: ",[81,374,375],{"class":135},"false",[81,377,378],{"class":91}," };\n",[81,380,382],{"class":83,"line":381},23,[81,383,384],{"class":91},"  }\n",[81,386,388],{"class":83,"line":387},24,[81,389,109],{"emptyLinePlaceholder":108},[81,391,393],{"class":83,"line":392},25,[81,394,396],{"class":395},"sAwPA","  \u002F\u002F 1. Sort all incoming parameters alphabetically, excluding the hash itself\n",[81,398,400,402,405,407,410,412,415,418,421,424,426,429,432,435,438,441,444,447],{"class":83,"line":399},26,[81,401,303],{"class":87},[81,403,404],{"class":135}," keys",[81,406,309],{"class":87},[81,408,409],{"class":91}," Array.",[81,411,95],{"class":118},[81,413,414],{"class":91},"(urlParams.",[81,416,417],{"class":118},"keys",[81,419,420],{"class":91},"()).",[81,422,423],{"class":118},"filter",[81,425,271],{"class":91},[81,427,428],{"class":128},"key",[81,430,431],{"class":87}," =>",[81,433,434],{"class":91}," key ",[81,436,437],{"class":87},"!==",[81,439,440],{"class":98}," 'hash'",[81,442,443],{"class":91},").",[81,445,446],{"class":118},"sort",[81,448,449],{"class":91},"();\n",[81,451,453],{"class":83,"line":452},27,[81,454,348],{"class":91},[81,456,458],{"class":83,"line":457},28,[81,459,460],{"class":395},"  \u002F\u002F 2. Re-create the verification data-check string\n",[81,462,464,466,469,471],{"class":83,"line":463},29,[81,465,303],{"class":87},[81,467,468],{"class":135}," dataCheckString",[81,470,309],{"class":87},[81,472,473],{"class":91}," keys\n",[81,475,477,480,483,485,487,489,492,494,497,500,502,504,506,508,510,513],{"class":83,"line":476},30,[81,478,479],{"class":91},"    .",[81,481,482],{"class":118},"map",[81,484,271],{"class":91},[81,486,428],{"class":128},[81,488,431],{"class":87},[81,490,491],{"class":98}," `${",[81,493,428],{"class":91},[81,495,496],{"class":98},"}=${",[81,498,499],{"class":91},"urlParams",[81,501,62],{"class":98},[81,503,334],{"class":118},[81,505,271],{"class":98},[81,507,428],{"class":91},[81,509,291],{"class":98},[81,511,512],{"class":98},"}`",[81,514,515],{"class":91},")\n",[81,517,519,521,524,526,529,532,534],{"class":83,"line":518},31,[81,520,479],{"class":91},[81,522,523],{"class":118},"join",[81,525,271],{"class":91},[81,527,528],{"class":98},"'",[81,530,531],{"class":135},"\\n",[81,533,528],{"class":98},[81,535,342],{"class":91},[81,537,539],{"class":83,"line":538},32,[81,540,109],{"emptyLinePlaceholder":108},[81,542,544],{"class":83,"line":543},33,[81,545,546],{"class":395},"  \u002F\u002F 3. Generate the secret cryptographic key\n",[81,548,550],{"class":83,"line":549},34,[81,551,552],{"class":395},"  \u002F\u002F We use the constant string \"WebAppData\" to sign the bot token first\n",[81,554,556,558,561,563],{"class":83,"line":555},35,[81,557,303],{"class":87},[81,559,560],{"class":135}," secretKey",[81,562,309],{"class":87},[81,564,565],{"class":91}," crypto\n",[81,567,569,571,574,576,579,581,584],{"class":83,"line":568},36,[81,570,479],{"class":91},[81,572,573],{"class":118},"createHmac",[81,575,271],{"class":91},[81,577,578],{"class":98},"'sha256'",[81,580,281],{"class":91},[81,582,583],{"class":98},"'WebAppData'",[81,585,515],{"class":91},[81,587,589,591,594],{"class":83,"line":588},37,[81,590,479],{"class":91},[81,592,593],{"class":118},"update",[81,595,596],{"class":91},"(botToken)\n",[81,598,600,602,605],{"class":83,"line":599},38,[81,601,479],{"class":91},[81,603,604],{"class":118},"digest",[81,606,449],{"class":91},[81,608,610],{"class":83,"line":609},39,[81,611,109],{"emptyLinePlaceholder":108},[81,613,615],{"class":83,"line":614},40,[81,616,617],{"class":395},"  \u002F\u002F 4. Calculate the expected hash of the sorted string\n",[81,619,621,623,626,628],{"class":83,"line":620},41,[81,622,303],{"class":87},[81,624,625],{"class":135}," computedHash",[81,627,309],{"class":87},[81,629,565],{"class":91},[81,631,633,635,637,639,641],{"class":83,"line":632},42,[81,634,479],{"class":91},[81,636,573],{"class":118},[81,638,271],{"class":91},[81,640,578],{"class":98},[81,642,643],{"class":91},", secretKey)\n",[81,645,647,649,651],{"class":83,"line":646},43,[81,648,479],{"class":91},[81,650,593],{"class":118},[81,652,653],{"class":91},"(dataCheckString)\n",[81,655,657,659,661,663,666],{"class":83,"line":656},44,[81,658,479],{"class":91},[81,660,604],{"class":118},[81,662,271],{"class":91},[81,664,665],{"class":98},"'hex'",[81,667,342],{"class":91},[81,669,671],{"class":83,"line":670},45,[81,672,109],{"emptyLinePlaceholder":108},[81,674,676],{"class":83,"line":675},46,[81,677,678],{"class":395},"  \u002F\u002F 5. Compare computed signature with the signature sent by the client\n",[81,680,682,684,687,689,692,695],{"class":83,"line":681},47,[81,683,303],{"class":87},[81,685,686],{"class":135}," isValid",[81,688,309],{"class":87},[81,690,691],{"class":91}," computedHash ",[81,693,694],{"class":87},"===",[81,696,697],{"class":91}," hash;\n",[81,699,701],{"class":83,"line":700},48,[81,702,109],{"emptyLinePlaceholder":108},[81,704,706,708,710,712],{"class":83,"line":705},49,[81,707,354],{"class":87},[81,709,357],{"class":91},[81,711,360],{"class":87},[81,713,714],{"class":91},"isValid) {\n",[81,716,718,720,722,724],{"class":83,"line":717},50,[81,719,369],{"class":87},[81,721,372],{"class":91},[81,723,375],{"class":135},[81,725,378],{"class":91},[81,727,729],{"class":83,"line":728},51,[81,730,384],{"class":91},[81,732,734],{"class":83,"line":733},52,[81,735,109],{"emptyLinePlaceholder":108},[81,737,739],{"class":83,"line":738},53,[81,740,741],{"class":395},"  \u002F\u002F Parse user data object if validation succeeded\n",[81,743,745,748],{"class":83,"line":744},54,[81,746,747],{"class":87},"  try",[81,749,122],{"class":91},[81,751,753,756,759,761,763,765,767,770],{"class":83,"line":752},55,[81,754,755],{"class":87},"    const",[81,757,758],{"class":135}," userRaw",[81,760,309],{"class":87},[81,762,331],{"class":91},[81,764,334],{"class":118},[81,766,271],{"class":91},[81,768,769],{"class":98},"'user'",[81,771,342],{"class":91},[81,773,775,777,780,782,784,786,789,792,795,797,800,803,805,808],{"class":83,"line":774},56,[81,776,755],{"class":87},[81,778,779],{"class":135}," user",[81,781,132],{"class":87},[81,783,119],{"class":118},[81,785,309],{"class":87},[81,787,788],{"class":91}," userRaw ",[81,790,791],{"class":87},"?",[81,793,794],{"class":135}," JSON",[81,796,62],{"class":91},[81,798,799],{"class":118},"parse",[81,801,802],{"class":91},"(userRaw) ",[81,804,132],{"class":87},[81,806,807],{"class":135}," undefined",[81,809,102],{"class":91},[81,811,813,815,817,820],{"class":83,"line":812},57,[81,814,369],{"class":87},[81,816,372],{"class":91},[81,818,819],{"class":135},"true",[81,821,822],{"class":91},", user };\n",[81,824,826,829,832],{"class":83,"line":825},58,[81,827,828],{"class":91},"  } ",[81,830,831],{"class":87},"catch",[81,833,834],{"class":91}," (error) {\n",[81,836,838,840,842,844],{"class":83,"line":837},59,[81,839,369],{"class":87},[81,841,372],{"class":91},[81,843,819],{"class":135},[81,845,378],{"class":91},[81,847,849],{"class":83,"line":848},60,[81,850,384],{"class":91},[81,852,854],{"class":83,"line":853},61,[81,855,207],{"class":91},[26,857,859],{"id":858},"_2-frontend-integration-theme-synchronization","2. Frontend Integration & Theme Synchronization",[11,861,862],{},"To deliver a premium UI\u002FUX, your Mini App should visually blend with the Telegram client’s dark\u002Flight settings. You can access the styles and control client-side behaviors using the official Telegram WebApp JS library.",[864,865,867],"h3",{"id":866},"step-1-include-the-script-in-nuxt-3-html","Step 1: Include the Script in Nuxt 3 \u002F HTML",[11,869,870,871,874],{},"Add the official script to your page header or use the ",[42,872,873],{},"useHead"," composable in Nuxt:",[34,876,878],{"className":75,"code":877,"language":77,"meta":40,"style":40},"\u002F\u002F app.vue or page layout\nuseHead({\n  script: [\n    { src: 'https:\u002F\u002Ftelegram.org\u002Fjs\u002Ftelegram-web-app.js', defer: true }\n  ]\n})\n",[42,879,880,885,892,897,913,918],{"__ignoreMap":40},[81,881,882],{"class":83,"line":84},[81,883,884],{"class":395},"\u002F\u002F app.vue or page layout\n",[81,886,887,889],{"class":83,"line":105},[81,888,873],{"class":118},[81,890,891],{"class":91},"({\n",[81,893,894],{"class":83,"line":112},[81,895,896],{"class":91},"  script: [\n",[81,898,899,902,905,908,910],{"class":83,"line":125},[81,900,901],{"class":91},"    { src: ",[81,903,904],{"class":98},"'https:\u002F\u002Ftelegram.org\u002Fjs\u002Ftelegram-web-app.js'",[81,906,907],{"class":91},", defer: ",[81,909,819],{"class":135},[81,911,912],{"class":91}," }\n",[81,914,915],{"class":83,"line":141},[81,916,917],{"class":91},"  ]\n",[81,919,920],{"class":83,"line":154},[81,921,922],{"class":91},"})\n",[864,924,926],{"id":925},"step-2-access-the-webapp-bridge-in-vue","Step 2: Access the WebApp Bridge in Vue",[11,928,929],{},"Create a Vue composable to access and synchronize Telegram styles:",[34,931,933],{"className":75,"code":932,"language":77,"meta":40,"style":40},"\u002F\u002F composables\u002FuseTelegram.ts\nimport { ref, onMounted } from 'vue';\n\nexport function useTelegram() {\n  const isReady = ref(false);\n  const user = ref\u003Cany>(null);\n\n  onMounted(() => {\n    const tg = (window as any).Telegram?.WebApp;\n    if (tg) {\n      tg.ready();\n      tg.expand(); \u002F\u002F Request the container to fill maximum vertical space\n      \n      user.value = tg.initDataUnsafe?.user;\n      isReady.value = true;\n\n      \u002F\u002F Apply Telegram theme colors to CSS custom properties\n      const root = document.documentElement;\n      root.style.setProperty('--color-tg-bg', tg.themeParams.bg_color);\n      root.style.setProperty('--color-tg-text', tg.themeParams.text_color);\n      root.style.setProperty('--color-tg-button', tg.themeParams.button_color);\n      root.style.setProperty('--color-tg-button-text', tg.themeParams.button_text_color);\n    }\n  });\n\n  return { isReady, user };\n}\n",[42,934,935,940,954,958,970,988,1012,1016,1029,1050,1058,1068,1081,1086,1097,1109,1113,1118,1131,1147,1161,1175,1189,1194,1199,1203,1211],{"__ignoreMap":40},[81,936,937],{"class":83,"line":84},[81,938,939],{"class":395},"\u002F\u002F composables\u002FuseTelegram.ts\n",[81,941,942,944,947,949,952],{"class":83,"line":105},[81,943,88],{"class":87},[81,945,946],{"class":91}," { ref, onMounted } ",[81,948,95],{"class":87},[81,950,951],{"class":98}," 'vue'",[81,953,102],{"class":91},[81,955,956],{"class":83,"line":112},[81,957,109],{"emptyLinePlaceholder":108},[81,959,960,962,964,967],{"class":83,"line":125},[81,961,262],{"class":87},[81,963,265],{"class":87},[81,965,966],{"class":118}," useTelegram",[81,968,969],{"class":91},"() {\n",[81,971,972,974,977,979,982,984,986],{"class":83,"line":141},[81,973,303],{"class":87},[81,975,976],{"class":135}," isReady",[81,978,309],{"class":87},[81,980,981],{"class":118}," ref",[81,983,271],{"class":91},[81,985,375],{"class":135},[81,987,342],{"class":91},[81,989,990,992,994,996,998,1001,1004,1007,1010],{"class":83,"line":154},[81,991,303],{"class":87},[81,993,779],{"class":135},[81,995,309],{"class":87},[81,997,981],{"class":118},[81,999,1000],{"class":91},"\u003C",[81,1002,1003],{"class":135},"any",[81,1005,1006],{"class":91},">(",[81,1008,1009],{"class":135},"null",[81,1011,342],{"class":91},[81,1013,1014],{"class":83,"line":167},[81,1015,109],{"emptyLinePlaceholder":108},[81,1017,1018,1021,1024,1027],{"class":83,"line":179},[81,1019,1020],{"class":118},"  onMounted",[81,1022,1023],{"class":91},"(() ",[81,1025,1026],{"class":87},"=>",[81,1028,122],{"class":91},[81,1030,1031,1033,1036,1038,1041,1044,1047],{"class":83,"line":191},[81,1032,755],{"class":87},[81,1034,1035],{"class":135}," tg",[81,1037,309],{"class":87},[81,1039,1040],{"class":91}," (window ",[81,1042,1043],{"class":87},"as",[81,1045,1046],{"class":135}," any",[81,1048,1049],{"class":91},").Telegram?.WebApp;\n",[81,1051,1052,1055],{"class":83,"line":204},[81,1053,1054],{"class":87},"    if",[81,1056,1057],{"class":91}," (tg) {\n",[81,1059,1060,1063,1066],{"class":83,"line":210},[81,1061,1062],{"class":91},"      tg.",[81,1064,1065],{"class":118},"ready",[81,1067,449],{"class":91},[81,1069,1070,1072,1075,1078],{"class":83,"line":215},[81,1071,1062],{"class":91},[81,1073,1074],{"class":118},"expand",[81,1076,1077],{"class":91},"(); ",[81,1079,1080],{"class":395},"\u002F\u002F Request the container to fill maximum vertical space\n",[81,1082,1083],{"class":83,"line":225},[81,1084,1085],{"class":91},"      \n",[81,1087,1088,1091,1094],{"class":83,"line":237},[81,1089,1090],{"class":91},"      user.value ",[81,1092,1093],{"class":87},"=",[81,1095,1096],{"class":91}," tg.initDataUnsafe?.user;\n",[81,1098,1099,1102,1104,1107],{"class":83,"line":249},[81,1100,1101],{"class":91},"      isReady.value ",[81,1103,1093],{"class":87},[81,1105,1106],{"class":135}," true",[81,1108,102],{"class":91},[81,1110,1111],{"class":83,"line":254},[81,1112,109],{"emptyLinePlaceholder":108},[81,1114,1115],{"class":83,"line":259},[81,1116,1117],{"class":395},"      \u002F\u002F Apply Telegram theme colors to CSS custom properties\n",[81,1119,1120,1123,1126,1128],{"class":83,"line":300},[81,1121,1122],{"class":87},"      const",[81,1124,1125],{"class":135}," root",[81,1127,309],{"class":87},[81,1129,1130],{"class":91}," document.documentElement;\n",[81,1132,1133,1136,1139,1141,1144],{"class":83,"line":321},[81,1134,1135],{"class":91},"      root.style.",[81,1137,1138],{"class":118},"setProperty",[81,1140,271],{"class":91},[81,1142,1143],{"class":98},"'--color-tg-bg'",[81,1145,1146],{"class":91},", tg.themeParams.bg_color);\n",[81,1148,1149,1151,1153,1155,1158],{"class":83,"line":345},[81,1150,1135],{"class":91},[81,1152,1138],{"class":118},[81,1154,271],{"class":91},[81,1156,1157],{"class":98},"'--color-tg-text'",[81,1159,1160],{"class":91},", tg.themeParams.text_color);\n",[81,1162,1163,1165,1167,1169,1172],{"class":83,"line":351},[81,1164,1135],{"class":91},[81,1166,1138],{"class":118},[81,1168,271],{"class":91},[81,1170,1171],{"class":98},"'--color-tg-button'",[81,1173,1174],{"class":91},", tg.themeParams.button_color);\n",[81,1176,1177,1179,1181,1183,1186],{"class":83,"line":366},[81,1178,1135],{"class":91},[81,1180,1138],{"class":118},[81,1182,271],{"class":91},[81,1184,1185],{"class":98},"'--color-tg-button-text'",[81,1187,1188],{"class":91},", tg.themeParams.button_text_color);\n",[81,1190,1191],{"class":83,"line":381},[81,1192,1193],{"class":91},"    }\n",[81,1195,1196],{"class":83,"line":387},[81,1197,1198],{"class":91},"  });\n",[81,1200,1201],{"class":83,"line":392},[81,1202,109],{"emptyLinePlaceholder":108},[81,1204,1205,1208],{"class":83,"line":399},[81,1206,1207],{"class":87},"  return",[81,1209,1210],{"class":91}," { isReady, user };\n",[81,1212,1213],{"class":83,"line":452},[81,1214,207],{"class":91},[26,1216,1218],{"id":1217},"_3-monetization-payments-via-telegram-stars","3. Monetization: Payments via Telegram Stars",[11,1220,1221,1222,357,1225,1228],{},"When operating inside Telegram, all digital services or content purchases must comply with Apple App Store and Google Play policies. Telegram enforces this by requiring the use of ",[15,1223,1224],{},"Telegram Stars",[42,1226,1227],{},"XTR",") for digital goods.",[11,1230,1231],{},"The flow for receiving Stars payments:",[1233,1234,1235,1242,1254,1260],"ol",{},[1236,1237,1238,1241],"li",{},[15,1239,1240],{},"Request Invoice",": The TWA requests the backend to generate an invoice.",[1236,1243,1244,1247,1248,1251,1252,62],{},[15,1245,1246],{},"Bot Sends Invoice",": The backend calls Bot API ",[42,1249,1250],{},"sendInvoice"," using the currency ",[42,1253,1227],{},[1236,1255,1256,1259],{},[15,1257,1258],{},"Client Checkout",": The Telegram client opens a native overlay allowing the user to pay using Stars purchased in-app.",[1236,1261,1262,1265,1266,1269],{},[15,1263,1264],{},"Verification",": Telegram sends a webhook ",[42,1267,1268],{},"successful_payment"," to your bot, which credits the user's account in your DB.",[11,1271,1272,1273,1278,1279,62],{},"In my Telegram bot hosting platform, ",[1274,1275,1277],"a",{"href":1276},"\u002Fprojects\u002Ftelego","TeleGo.io",", we provide exactly these billing options, allowing users to spin up their own TWAs and receive Stars instantly. Additionally, we support hybrid human-AI helpdesks, which you can learn to build in my guide on ",[1274,1280,1282],{"href":1281},"\u002Fblog\u002Ftelegram-bot-ai-rag-support","RAG AI Customer Support Bots",[11,1284,1285,1286,1290],{},"For physical goods and consulting services, traditional gateways can be used. Read my ",[1274,1287,1289],{"href":1288},"\u002Fblog\u002Fsaas-stripe-billing-integration","SaaS Stripe Billing Integration guide"," for Express\u002FTypeScript templates.",[26,1292,1294],{"id":1293},"sources-and-documentation","Sources and documentation",[1296,1297,1298,1307],"ul",{},[1236,1299,1300,1306],{},[1274,1301,1305],{"href":1302,"rel":1303},"https:\u002F\u002Fcore.telegram.org\u002Fbots\u002Fwebapps",[1304],"nofollow","Telegram Mini Apps"," — the official WebApp SDK and initData documentation",[1236,1308,1309,1314],{},[1274,1310,1313],{"href":1311,"rel":1312},"https:\u002F\u002Fcore.telegram.org\u002Fbots\u002Fpayments",[1304],"Bot Payments API"," — invoices, Telegram Stars, and payment webhooks",[11,1316,1317],{},"By combining native web frameworks with the Telegram WebApp API, developers can ship complex SaaS platforms and digital products directly into active messaging channels.",[11,1319,1320,1321,1325,1326,1330],{},"If you are planning to build a high-performance Telegram Mini App with secure billing integrations and dynamic frontend design, check out my ",[1274,1322,1324],{"href":1323},"\u002Ftelegram-bots","Telegram Bot Development Service"," or request a ",[1274,1327,1329],{"href":1328},"\u002Fconsultations","Technical Architecture Consultation"," to get a production blueprint.",[1332,1333,1334],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}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":40,"searchDepth":105,"depth":105,"links":1336},[1337,1338,1340,1344,1345],{"id":28,"depth":105,"text":29},{"id":46,"depth":105,"text":1339},"1. Security First: Validating the initData Payload",{"id":858,"depth":105,"text":859,"children":1341},[1342,1343],{"id":866,"depth":112,"text":867},{"id":925,"depth":112,"text":926},{"id":1217,"depth":105,"text":1218},{"id":1293,"depth":105,"text":1294},"2026-07-05","A comprehensive developer's guide to using Telegram Mini Apps as a dynamic web frontend, implementing secure hash validation, and processing in-app purchases.","md",[1350,1353,1356],{"q":1351,"a":1352},"How is a Telegram Mini App different from a regular bot?","A bot communicates through messages and buttons, while a Mini App opens a full web interface inside Telegram: dashboards, catalogs, forms, charts. It's an SPA running in a WebView with its own frontend, and authorization happens automatically through the Telegram account.",{"q":1354,"a":1355},"How do I verify that user data in a Mini App isn't forged?","Through cryptographic initData validation: Telegram signs the user data with an HMAC-SHA256 signature derived from the bot token. The backend must recompute and compare the signature on every request — without it, anyone can impersonate any user.",{"q":1357,"a":1358},"When are Telegram Stars mandatory, and when can I use Stripe?","Digital goods and subscriptions inside a Mini App must be paid with Telegram Stars per Apple and Google policies. Physical goods, services, and consulting can be sold through classic gateways like Stripe.","\u002Fimages\u002Fblog\u002Fblog_telegram_twa.jpg","en",{},"\u002Fblog\u002Fen\u002Ftelegram-web-apps-sells",{"title":6,"description":1347},"blog\u002Fen\u002Ftelegram-web-apps-sells",[1366,1367,1368,1369,1370],"Telegram","Mini Apps","SaaS","Node.js","Frontend","4blcVbDR853MsonsChj72pfs0C4mqm-aL83XkBOZ0io",{"id":1373,"title":1374,"body":1375,"date":1940,"description":1941,"extension":1348,"faq":1942,"image":1952,"lang":1360,"meta":1953,"navigation":108,"path":1954,"published":108,"readTime":215,"seo":1955,"stem":1956,"tags":1957,"updated":1346,"__hash__":1962},"blog\u002Fblog\u002Fen\u002Fgenerative-engine-optimization-geo.md","Generative Engine Optimization (GEO): The New SEO for AI Search",{"type":8,"value":1376,"toc":1929},[1377,1380,1383,1389,1392,1396,1399,1405,1408,1412,1420,1423,1522,1529,1533,1537,1540,1554,1558,1561,1575,1579,1582,1586,1589,1864,1876,1883,1885,1911,1914,1926],[11,1378,1379],{},"The web search ecosystem is undergoing its most revolutionary change since Google’s inception in 1998. Traditional search engine optimization (SEO) is built on ranking links on a Search Engine Results Page (SERP). Today, however, millions of users are bypassing search result pages altogether. They query conversational AI assistants—such as ChatGPT Search, Perplexity, Gemini, and Claude—to get direct, synthesized answers.",[11,1381,1382],{},"If your product, SaaS, or agency is not recommended and cited in these AI responses, your business is virtually invisible to a rapidly growing demographic of buyers.",[11,1384,1385,1386,62],{},"To stay competitive, you must optimize your site for large language model (LLM) search engines. This is the discipline of ",[15,1387,1388],{},"Generative Engine Optimization (GEO)",[11,1390,1391],{},"In this deep dive, we will explore how conversational search engines work, analyze academic ranking factors, and implement technical adjustments to secure your brand's placement in AI summaries.",[26,1393,1395],{"id":1394},"the-ai-search-rag-retrieval-pipeline","The AI Search (RAG) Retrieval Pipeline",[11,1397,1398],{},"Unlike classic crawlers that map keywords to index scores, AI search engines use a hybrid retrieval pipeline:",[34,1400,1403],{"className":1401,"code":1402,"language":39,"meta":40},[37],"[User asks: \"Best multi-tenant CRM for real estate\"]\n                             │\n                             v\n           (AI Query Understanding & Search)\n    LLM rewrites query -> Runs web search (Bing\u002FGoogle API)\n                             │\n                             v\n           (Scraping & Embedding top 10 results)\n     AI scrapers read HTML -> Vectorize content chunks\n                             │\n                             v\n            (RAG Re-ranking & Synthesis)\n     Matches question vector against scraped chunks ->\n  Selects top 3 sources -> Synthesizes single answer with links\n                             │\n                             v\n[Output: \"I recommend AcmeCRM [1] because of its postgres schema isolation [2]\"]\n",[42,1404,1402],{"__ignoreMap":40},[11,1406,1407],{},"To rank in this ecosystem, your content must satisfy two criteria: it must appear in the top search indexes, and it must be structured in a way that the LLM re-ranker selects it as the most authoritative, easy-to-summarize source.",[26,1409,1411],{"id":1410},"_1-key-geo-optimization-techniques-backed-by-research","1. Key GEO Optimization Techniques (Backed by Research)",[11,1413,1414,1415,1419],{},"In 2023, researchers from Princeton, Georgia Tech, and the Allen Institute for AI published a landmark study titled ",[1416,1417,1418],"em",{},"“Generative Engine Optimization”",". They systematically tested various content modification techniques to see what factors influence an LLM’s probability of citing a website.",[11,1421,1422],{},"Here is the data-backed rubric of what works best:",[1424,1425,1426,1443],"table",{},[1427,1428,1429],"thead",{},[1430,1431,1432,1437,1440],"tr",{},[1433,1434,1436],"th",{"align":1435},"left","GEO Strategy",[1433,1438,1439],{"align":1435},"What it means",[1433,1441,1442],{"align":1435},"Citation Increase",[1444,1445,1446,1462,1477,1492,1507],"tbody",{},[1430,1447,1448,1454,1457],{},[1449,1450,1451],"td",{"align":1435},[15,1452,1453],{},"Cite Sources",[1449,1455,1456],{"align":1435},"Adding outbound links to high-authority academic papers, government stats, or news portals.",[1449,1458,1459],{"align":1435},[15,1460,1461],{},"+40.3%",[1430,1463,1464,1469,1472],{},[1449,1465,1466],{"align":1435},[15,1467,1468],{},"Include Statistics",[1449,1470,1471],{"align":1435},"Replacing vague claims with verified quantitative data and numerical metrics.",[1449,1473,1474],{"align":1435},[15,1475,1476],{},"+37.5%",[1430,1478,1479,1484,1487],{},[1449,1480,1481],{"align":1435},[15,1482,1483],{},"Information Gain",[1449,1485,1486],{"align":1435},"Adding unique data or insights not present in other top search results.",[1449,1488,1489],{"align":1435},[15,1490,1491],{},"+32.1%",[1430,1493,1494,1499,1502],{},[1449,1495,1496],{"align":1435},[15,1497,1498],{},"Q&A Formatting",[1449,1500,1501],{"align":1435},"Structuring headlines as questions followed by a direct, concise answer.",[1449,1503,1504],{"align":1435},[15,1505,1506],{},"+25.8%",[1430,1508,1509,1514,1517],{},[1449,1510,1511],{"align":1435},[15,1512,1513],{},"Markdown Tables",[1449,1515,1516],{"align":1435},"Organizing complex comparisons in clean markdown tables.",[1449,1518,1519],{"align":1435},[15,1520,1521],{},"+18.2%",[11,1523,1524,1525,1528],{},"Traditional SEO tactics like keyword stuffing actually ",[1416,1526,1527],{},"decrease"," citation scores in LLM re-rankers because they reduce readability and lower the model's summarization score.",[26,1530,1532],{"id":1531},"_2-practical-technical-geo-checklist","2. Practical Technical GEO Checklist",[864,1534,1536],{"id":1535},"a-implement-qa-style-h2h3-headlines","A. Implement Q&A-Style H2\u002FH3 Headlines",[11,1538,1539],{},"AI models are trained to map answers to user queries. If a user asks a question, the LLM will scan search results for exact matching headers.",[1296,1541,1542,1548],{},[1236,1543,1544,1547],{},[1416,1545,1546],{},"Incorrect",": \"Our Billing Infrastructure Customizations\"",[1236,1549,1550,1553],{},[1416,1551,1552],{},"Correct",": \"How does the platform handle subscription billing?\" Follow this header immediately with a clear, concise 2-sentence summary of your architecture, followed by deeper details.",[864,1555,1557],{"id":1556},"b-add-outbound-citation-anchors","B. Add Outbound Citation Anchors",[11,1559,1560],{},"When referencing industry standards, link to authoritative repositories.",[1296,1562,1563],{},[1236,1564,1565,1568,1569,1574],{},[1416,1566,1567],{},"Example",": \"According to the ",[1274,1570,1573],{"href":1571,"rel":1572},"https:\u002F\u002Fowasp.org\u002Fwww-project-top-ten\u002F",[1304],"OWASP Top 10 Security Standards",", input sanitization is critical to prevent injection attacks...\"\nThis outbound link signals high authority to the LLM re-ranker.",[864,1576,1578],{"id":1577},"c-optimize-for-readability-flesch-kincaid-score","C. Optimize for Readability (Flesch-Kincaid Score)",[11,1580,1581],{},"LLMs prefer texts that are easy to parse and compile. Use clear, active voice, short sentences, and structured bullet points. Avoid flowery promotional adjectives.",[26,1583,1585],{"id":1584},"_3-feeding-clean-data-to-ai-bots-using-json-ld","3. Feeding Clean Data to AI bots using JSON-LD",[11,1587,1588],{},"To remove all ambiguity about your services, pricing, and entity relations, output clean semantic structures. Here is a JSON-LD snippet for a consultancy service that should be dynamically injected into your site's header:",[34,1590,1594],{"className":1591,"code":1592,"language":1593,"meta":40,"style":40},"language-json shiki shiki-themes github-dark","{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"ConsultingService\",\n  \"@id\": \"https:\u002F\u002Falexrel.com\u002Fconsultations#service\",\n  \"name\": \"Technical Architecture Consultation\",\n  \"description\": \"Professional codebase audits, database scaling reviews, and SaaS MVP planning.\",\n  \"provider\": {\n    \"@type\": \"Person\",\n    \"name\": \"Alex Rel\",\n    \"jobTitle\": \"Senior Fullstack Developer\",\n    \"url\": \"https:\u002F\u002Falexrel.com\"\n  },\n  \"offers\": {\n    \"@type\": \"Offer\",\n    \"priceCurrency\": \"USD\",\n    \"price\": \"250\",\n    \"priceSpecification\": {\n      \"@type\": \"UnitPriceSpecification\",\n      \"priceType\": \"https:\u002F\u002Fschema.org\u002FRecurringPrice\",\n      \"billingIncrement\": 1,\n      \"referenceQuantity\": {\n        \"@type\": \"QuantitativeValue\",\n        \"value\": 1,\n        \"unitCode\": \"HUR\"\n      }\n    }\n  }\n}\n","json",[42,1595,1596,1601,1615,1627,1639,1651,1663,1671,1683,1695,1707,1717,1722,1729,1740,1752,1764,1771,1783,1795,1807,1814,1826,1837,1847,1852,1856,1860],{"__ignoreMap":40},[81,1597,1598],{"class":83,"line":84},[81,1599,1600],{"class":91},"{\n",[81,1602,1603,1606,1609,1612],{"class":83,"line":105},[81,1604,1605],{"class":135},"  \"@context\"",[81,1607,1608],{"class":91},": ",[81,1610,1611],{"class":98},"\"https:\u002F\u002Fschema.org\"",[81,1613,1614],{"class":91},",\n",[81,1616,1617,1620,1622,1625],{"class":83,"line":112},[81,1618,1619],{"class":135},"  \"@type\"",[81,1621,1608],{"class":91},[81,1623,1624],{"class":98},"\"ConsultingService\"",[81,1626,1614],{"class":91},[81,1628,1629,1632,1634,1637],{"class":83,"line":125},[81,1630,1631],{"class":135},"  \"@id\"",[81,1633,1608],{"class":91},[81,1635,1636],{"class":98},"\"https:\u002F\u002Falexrel.com\u002Fconsultations#service\"",[81,1638,1614],{"class":91},[81,1640,1641,1644,1646,1649],{"class":83,"line":141},[81,1642,1643],{"class":135},"  \"name\"",[81,1645,1608],{"class":91},[81,1647,1648],{"class":98},"\"Technical Architecture Consultation\"",[81,1650,1614],{"class":91},[81,1652,1653,1656,1658,1661],{"class":83,"line":154},[81,1654,1655],{"class":135},"  \"description\"",[81,1657,1608],{"class":91},[81,1659,1660],{"class":98},"\"Professional codebase audits, database scaling reviews, and SaaS MVP planning.\"",[81,1662,1614],{"class":91},[81,1664,1665,1668],{"class":83,"line":167},[81,1666,1667],{"class":135},"  \"provider\"",[81,1669,1670],{"class":91},": {\n",[81,1672,1673,1676,1678,1681],{"class":83,"line":179},[81,1674,1675],{"class":135},"    \"@type\"",[81,1677,1608],{"class":91},[81,1679,1680],{"class":98},"\"Person\"",[81,1682,1614],{"class":91},[81,1684,1685,1688,1690,1693],{"class":83,"line":191},[81,1686,1687],{"class":135},"    \"name\"",[81,1689,1608],{"class":91},[81,1691,1692],{"class":98},"\"Alex Rel\"",[81,1694,1614],{"class":91},[81,1696,1697,1700,1702,1705],{"class":83,"line":204},[81,1698,1699],{"class":135},"    \"jobTitle\"",[81,1701,1608],{"class":91},[81,1703,1704],{"class":98},"\"Senior Fullstack Developer\"",[81,1706,1614],{"class":91},[81,1708,1709,1712,1714],{"class":83,"line":210},[81,1710,1711],{"class":135},"    \"url\"",[81,1713,1608],{"class":91},[81,1715,1716],{"class":98},"\"https:\u002F\u002Falexrel.com\"\n",[81,1718,1719],{"class":83,"line":215},[81,1720,1721],{"class":91},"  },\n",[81,1723,1724,1727],{"class":83,"line":225},[81,1725,1726],{"class":135},"  \"offers\"",[81,1728,1670],{"class":91},[81,1730,1731,1733,1735,1738],{"class":83,"line":237},[81,1732,1675],{"class":135},[81,1734,1608],{"class":91},[81,1736,1737],{"class":98},"\"Offer\"",[81,1739,1614],{"class":91},[81,1741,1742,1745,1747,1750],{"class":83,"line":249},[81,1743,1744],{"class":135},"    \"priceCurrency\"",[81,1746,1608],{"class":91},[81,1748,1749],{"class":98},"\"USD\"",[81,1751,1614],{"class":91},[81,1753,1754,1757,1759,1762],{"class":83,"line":254},[81,1755,1756],{"class":135},"    \"price\"",[81,1758,1608],{"class":91},[81,1760,1761],{"class":98},"\"250\"",[81,1763,1614],{"class":91},[81,1765,1766,1769],{"class":83,"line":259},[81,1767,1768],{"class":135},"    \"priceSpecification\"",[81,1770,1670],{"class":91},[81,1772,1773,1776,1778,1781],{"class":83,"line":300},[81,1774,1775],{"class":135},"      \"@type\"",[81,1777,1608],{"class":91},[81,1779,1780],{"class":98},"\"UnitPriceSpecification\"",[81,1782,1614],{"class":91},[81,1784,1785,1788,1790,1793],{"class":83,"line":321},[81,1786,1787],{"class":135},"      \"priceType\"",[81,1789,1608],{"class":91},[81,1791,1792],{"class":98},"\"https:\u002F\u002Fschema.org\u002FRecurringPrice\"",[81,1794,1614],{"class":91},[81,1796,1797,1800,1802,1805],{"class":83,"line":345},[81,1798,1799],{"class":135},"      \"billingIncrement\"",[81,1801,1608],{"class":91},[81,1803,1804],{"class":135},"1",[81,1806,1614],{"class":91},[81,1808,1809,1812],{"class":83,"line":351},[81,1810,1811],{"class":135},"      \"referenceQuantity\"",[81,1813,1670],{"class":91},[81,1815,1816,1819,1821,1824],{"class":83,"line":366},[81,1817,1818],{"class":135},"        \"@type\"",[81,1820,1608],{"class":91},[81,1822,1823],{"class":98},"\"QuantitativeValue\"",[81,1825,1614],{"class":91},[81,1827,1828,1831,1833,1835],{"class":83,"line":381},[81,1829,1830],{"class":135},"        \"value\"",[81,1832,1608],{"class":91},[81,1834,1804],{"class":135},[81,1836,1614],{"class":91},[81,1838,1839,1842,1844],{"class":83,"line":387},[81,1840,1841],{"class":135},"        \"unitCode\"",[81,1843,1608],{"class":91},[81,1845,1846],{"class":98},"\"HUR\"\n",[81,1848,1849],{"class":83,"line":392},[81,1850,1851],{"class":91},"      }\n",[81,1853,1854],{"class":83,"line":399},[81,1855,1193],{"class":91},[81,1857,1858],{"class":83,"line":452},[81,1859,384],{"class":91},[81,1861,1862],{"class":83,"line":457},[81,1863,207],{"class":91},[11,1865,1866,1867,1870,1871,1875],{},"When optimizing my own projects, such as the ",[1274,1868,1869],{"href":1276},"TeleGo.io platform"," and the ",[1274,1872,1874],{"href":1873},"\u002Fprojects\u002Flingvohabit","LingvoHabit language portal",", I implemented these precise structural adjustments. Today, both services are successfully cataloged and actively cited in real-time ChatGPT Search and Perplexity queries.",[11,1877,1878,1879,62],{},"To learn how to configure your robots.txt and schema structures to facilitate this, read my technical guide on ",[1274,1880,1882],{"href":1881},"\u002Fblog\u002Fwebsite-optimization-ai-crawlers","Optimizing your Website for AI Crawlers: Robots.txt & JSON-LD",[26,1884,1294],{"id":1293},[1296,1886,1887,1895,1903],{},[1236,1888,1889,1894],{},[1274,1890,1893],{"href":1891,"rel":1892},"https:\u002F\u002Farxiv.org\u002Fabs\u002F2311.09735",[1304],"GEO: Generative Engine Optimization"," — the original Princeton \u002F Georgia Tech \u002F Allen AI study behind the strategy table above",[1236,1896,1897,1902],{},[1274,1898,1901],{"href":1899,"rel":1900},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs",[1304],"Google Search Central"," — official documentation on indexing and structured data",[1236,1904,1905,1910],{},[1274,1906,1909],{"href":1907,"rel":1908},"https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fbots",[1304],"OpenAI crawler documentation"," — how GPTBot and OAI-SearchBot scan websites",[11,1912,1913],{},"By structuring your content for the Generative Web today, you secure your brand's presence in the AI search portals of tomorrow.",[11,1915,1916,1917,1921,1922,1925],{},"If you want to implement GEO strategies, perform an AI search audit of your website, or optimize your content for ChatGPT and Perplexity, explore my ",[1274,1918,1920],{"href":1919},"\u002Fgeo-seo","GEO & SEO Optimization Services"," or book a ",[1274,1923,1924],{"href":1328},"Technical Consultation"," to get started.",[1332,1927,1928],{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}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":40,"searchDepth":105,"depth":105,"links":1930},[1931,1932,1933,1938,1939],{"id":1394,"depth":105,"text":1395},{"id":1410,"depth":105,"text":1411},{"id":1531,"depth":105,"text":1532,"children":1934},[1935,1936,1937],{"id":1535,"depth":112,"text":1536},{"id":1556,"depth":112,"text":1557},{"id":1577,"depth":112,"text":1578},{"id":1584,"depth":105,"text":1585},{"id":1293,"depth":105,"text":1294},"2026-07-02","A technical guide on Generative Engine Optimization (GEO) strategies to improve brand citation and recommendation frequencies in ChatGPT, Perplexity, and Gemini.",[1943,1946,1949],{"q":1944,"a":1945},"What is GEO in simple terms?","GEO (Generative Engine Optimization) is optimizing a website so AI engines — ChatGPT, Perplexity, Gemini — can find, cite, and recommend your brand inside their answers. Where SEO fights for a ranking position, GEO fights for a mention inside the generated answer itself.",{"q":1947,"a":1948},"Does GEO replace classic SEO?","No, they complement each other. AI engines ride on classic search indexes (ChatGPT Search uses Bing, Gemini uses Google), so GEO doesn't work without basic indexability. SEO brings traffic from result pages; GEO brings mentions and clicks from AI answers.",{"q":1950,"a":1951},"Which GEO techniques deliver the biggest lift?","Per the Princeton \u002F Georgia Tech \u002F Allen AI study: citing authoritative sources (+40%), concrete statistics in the text (+37%), unique facts competitors don't have (+32%), and question-and-answer headings (+26%).","\u002Fimages\u002Fblog\u002Fblog_geo_seo.jpg",{},"\u002Fblog\u002Fen\u002Fgenerative-engine-optimization-geo",{"title":1374,"description":1941},"blog\u002Fen\u002Fgenerative-engine-optimization-geo",[1958,1959,1960,1961],"GEO","SEO","AI","Marketing","TKFkrhvWGfdJMdezJ6T4Sl12RWptm2ar9L2mwKcgEfM",1784561425258]