VIEW IN TELEGRAM

TMA Ad Landing

Multi-platform ad attribution redirect for Telegram Mini-Apps

Usage

https://tmetlink.com/{botUsername}/{appName}?agency_id=AGENCY&utm_source=X&utm_medium=Y&...

 deep link redirect (skips t.me web page):
  tg://resolve?domain={botUsername}&appname={appName}&startapp={base64url_encoded_params}

 CTA fallback (if Telegram not installed):
  https://t.me/{botUsername}/{appName}?startapp={base64url_encoded_params}

startapp limit: 512 chars, base64url-safe only [A-Za-z0-9_-]. (For reference: the non-mini-app ?start= bot deep link is capped at 64 chars — too tight to fit click_id + agency + UTMs, which is why this service uses mini-app links exclusively.)

Examples

Gift Fest (ru):  https://tmetlink.com/giftfest2_bot/app?agency_id=mn&lang=ru&utm_source=test1&utm_medium=test2&utm_campaign=test3&utm_content=test4&utm_term=test5&ad_id=test6&fbclid=IwY2xjawRDnSVleHRuA2FlbQIxMABicmlkETF2eHFpTVFJV3BpNXhieTU0c3J0YwZhcHBfaWQQMjIyMDM5MTc4ODIwMDg5MgABHsACAKT7QmVRW9oM7c5e37lczqpDlRMl09-Y6Xmpo71TIV7sAllQ9ov3btFb_aem_ha4IyVoN-RtWmXNpvOgvhg
                  tg://resolve?domain=giftfest2_bot&appname=app&startapp=VD1WMVN0R1hSOF9aNWpkSGk2Qm15VHgmQUc9bW4mTE49cnUmVVM9dGVzdDEmVU09dGVzdDImVUNQPXRlc3QzJlVDPXRlc3Q0JlVUPXRlc3Q1

Gift Fest (en):  https://tmetlink.com/giftfest2_bot/app?agency_id=mn&lang=en&utm_source=test1&utm_medium=test2&utm_campaign=test3&utm_content=test4&utm_term=test5&ad_id=test6&fbclid=IwY2xjawRDnSVleHRuA2FlbQIxMABicmlkETF2eHFpTVFJV3BpNXhieTU0c3J0YwZhcHBfaWQQMjIyMDM5MTc4ODIwMDg5MgABHsACAKT7QmVRW9oM7c5e37lczqpDlRMl09-Y6Xmpo71TIV7sAllQ9ov3btFb_aem_ha4IyVoN-RtWmXNpvOgvhg
                  tg://resolve?domain=giftfest2_bot&appname=app&startapp=VD1LMllwTFJxM1Z4Qm44TWVDcFhnWWomQUc9bW4mTE49ZW4mVVM9dGVzdDEmVU09dGVzdDImVUNQPXRlc3QzJlVDPXRlc3Q0JlVUPXRlc3Q1

Mira:            https://tmetlink.com/mira_ibot/app?agency_id=ts&lang=en&utm_source=meta&utm_medium=cpc&utm_campaign=launch
                  tg://resolve?domain=mira_ibot&appname=app&startapp=VD1tMVJhWHl6OV9BYkMyZEVmR2hJajAmQUc9dHMmTE49ZW4mVVM9bWV0YSZVTT1jcGMmVUNQPWxhdW5jaA

Tonstakers:      https://tmetlink.com/tonstakers_bot/app?agency_id=mn&lang=en&utm_source=google&utm_medium=cpc&utm_campaign=staking
                  tg://resolve?domain=tonstakers_bot&appname=app&startapp=VD10Uy1LOXBRNFdtWDJyTDd2WWJOMWMmQUc9bW4mTE49ZW4mVVM9Z29vZ2xlJlVNPWNwYyZVQ1A9c3Rha2luZw

Tribute:         https://tmetlink.com/subscribeappbot/app?agency_id=ts&lang=ru&utm_source=tiktok&utm_medium=video&utm_campaign=growth
                  tg://resolve?domain=subscribeappbot&appname=app&startapp=VD1UcjFiVXQzLVg5elAyX0tqUTh3QXYmQUc9dHMmTE49cnUmVVM9dGlrdG9rJlVNPXZpZGVvJlVDUD1ncm93dGg

StonFi:          https://tmetlink.com/ston_app_bot/app?agency_id=mn&lang=en&utm_source=yandex&utm_medium=cpc&utm_campaign=dex
                  tg://resolve?domain=ston_app_bot&appname=app&startapp=VD1TdDBuRjEtRDN4UXBfWjhtQWJWNHkmQUc9bW4mTE49ZW4mVVM9eWFuZGV4JlVNPWNwYyZVQ1A9ZGV4

startapp encoded length: Gift Fest example = 81 raw → 108 / 512. Typical (T + AG + LN + source/medium): 54 raw → 72 / 512. fbclid (~185 chars) is NOT in startapp — it goes to BQ via sGTM.

T (click_id) is the primary join key: sGTM logs the landing page hit to BigQuery with T, the TMA backend decodes T from startapp and stores it with the conversion event. Airflow joins on click_id to match ad click → conversion for offline postbacks.

Variable Parameters

URL params with a constrained set of values:

ParamSlugsDefault
langen, ru, es, pt, fr, de, ar, zhen
themelight, darkOS preference (prefers-color-scheme)

How lang works: the landing calls bot-info (Cloud Function), which opens a Telegram MTProto connection with lang_code=<lang> and runs users.GetFullUser(@bot). Telegram returns the bot name and about-text in that language — whatever the bot owner registered via BotFather. Static UI strings (CTA, "DOWNLOAD FOR" prefix, monthly-users suffix) are baked into custom.js for the 8 listed slugs.

To enable a new language (or improve an existing one):
1. Bot owner in BotFather: /setname and /setabouttext → pick the bot → choose the target language → submit the localized name and bio. Without this, Telegram falls back to the default (usually English) for that lang.
2. Landing UI strings: extend the STRINGS map in static/custom.js with cta, title, mau, dl for the new lang and redeploy. Adding a slug here also widens the lang table above.

Decoded Payload (startapp)

The original URL contains many params (fbclid, ad_id, etc.), but only the minimal set is encoded into startapp. Everything else goes to sGTM → BigQuery and is joined later by click_id.

T=V1StGXR8_Z5jdHi6BmyTx&AG=mn&LN=ru&US=test1&UM=test2&UCP=test3&UC=test4&UT=test5

Which parses to:

KeyValueSource
TV1StGXR8_Z5jdHi6BmyTxclick_id (generated by JS, nanoid 21 chars)
AGmnagency_id (URL)
LNrulang (URL, default: en)
UStest1utm_source (URL)
UMtest2utm_medium (URL)
UCPtest3utm_campaign (URL)
UCtest4utm_content (URL)
UTtest5utm_term (URL)

fbclid, ad_id, gclid, and all other params from the URL are not in startapp — they are logged to BigQuery via sGTM with the same click_id and joined later by Airflow.

~80 raw chars → ~110 base64url / 512 limit. Well within bounds.

Parameters Captured

Passed to TMA via startapp (base64url-encoded)

Minimal set — everything the TMA needs for analytics and conversion matching:

KeyInputSourcePurpose
Tclick_idJS (nanoid)Primary join key — links this ad click to the TMA conversion event. Airflow joins landing_hits.click_id = conversions.click_id for offline postbacks.
AGagency_idURLAgency/pixel routing: ts → 1112919053742027, mn → 1921519221768719
LNlangURLLanguage code (en, ru, es, etc.). Controls landing page i18n.
USutm_sourceURLTraffic source
UMutm_mediumURLMarketing medium
UCPutm_campaignURLCampaign name
UCutm_contentURLAd content variant
UTutm_termURLSearch term
PCpartner_codeURLPartner code
RCref_codeURLReferral code

Stored via sGTM → BigQuery (attributed to click_id)

All URL params + synthesized values are sent to sGTM via sendBeacon and logged to BigQuery. The TMA doesn't need these — Airflow retrieves them by joining on click_id.

InputSourcePurpose
Platform Click IDs
fbclidURLMeta click ID
gclidURLGoogle Ads click ID
gbraidURLGoogle privacy-compliant aggregate click ID
wbraidURLGoogle privacy-compliant web-to-app click ID
ttclidURLTikTok Ads click ID
yclidURLYandex Direct click ID
ysclidURLYandex Search click ID
tgclidURLTelegram Ads click ID
Meta Ads Parameters
campaign_idURLCampaign ID ({{campaign.id}})
adset_idURLAd set ID ({{adset.id}})
ad_idURLAd ID ({{ad.id}})
campaign_nameURLCampaign name ({{campaign.name}})
adset_nameURLAd set name ({{adset.name}})
ad_nameURLAd name ({{ad.name}})
placementURLAd placement ({{placement}})
site_source_nameURLSite source ({{site_source_name}})
Synthesized by JS (Meta attribution)
fbcJSMeta CAPI click ID: fb.1.{timestamp}.{fbclid}
fbpJSMeta CAPI browser ID: fb.1.{timestamp}.{random}
Custom
partner_codeURLPartner code
ref_codeURLReferral code
Server-side (captured automatically)
client_ip_addresssGTMFrom request headers
client_user_agentsGTMFrom request headers

All params above are logged to BigQuery with the same click_id (T). When the TMA reports a conversion, Airflow joins on click_id to retrieve the full attribution data for offline postbacks to Meta CAPI, Google Ads, TikTok, Yandex.

System Diagram

Ad Platforms (Meta/Google/TikTok/Yandex/Telegram)
       ↓ ad click (fbclid, gclid, ttclid, yclid, agency_id, UTMs)

tma-ad-landing (Cloud Run)
  generate click_id → synthesize fbc/fbp
  sendBeacon → sGTM        redirect → TMA
  (all params)               (click_id + AG + UTMs)
       ↓                          ↓

sGTM (Cloud Run)              Telegram TMA (per product)
  → BQ streaming               On conversion:
  → Meta CAPI*                 write to BQ with click_id
  → Google Ads*
  → TikTok/Yandex*            *=TODO
       ↓                          ↓

BigQuery
  landing_sgtm_events    conversions (per product)
  (shared, all clicks)   (per product TMA backend)
         ←— JOIN on click_id —→
                  ↓

Airflow DAG (per product)
  → Meta CAPI offline conversions
  → Google Ads Enhanced Conversions
  → TikTok Events API
  → Yandex offline conversions