A deep link campaign that performs well in the US might fail in Germany. App store availability, language, regulatory environment, device distribution, and user behavior all vary by geography. Geographic analytics reveal these differences so you can optimize campaigns for each market.
This guide covers geographic analytics for deep link campaigns. For deep link analytics broadly, see deep link analytics: measuring what matters. For localizing smart banners, see localizing smart banners for global audiences.
The analytics breakdown grid with top routes, platforms, devices, and countries.
Why Geography Matters for Deep Links
Platform Distribution
| Country | iOS Share | Android Share | Impact on Deep Links |
|---|---|---|---|
| US | ~55% | ~45% | Balanced, optimize both |
| UK | ~50% | ~50% | Balanced |
| Germany | ~30% | ~70% | Prioritize App Links |
| India | ~3% | ~97% | Android-only strategy |
| Japan | ~65% | ~35% | Prioritize Universal Links |
If your deep links work perfectly on iOS but have issues on Android, you are losing 97% of your audience in India.
App Store Availability
Deep links that redirect to the app store fail if the app is not available in that country's store. Your fallback page should detect the user's country and show appropriate messaging.
Regulatory Environment
- EU: GDPR affects tracking and consent requirements for deep link analytics.
- California: CCPA requires disclosure of data collection practices.
- China: Links to Google Play do not work. Alternative stores (Huawei AppGallery, Xiaomi) needed.
- Russia: Google Play has restrictions. Consider alternative distribution.
Geographic Metrics
Country-Level Performance
SELECT
country,
COUNT(*) AS clicks,
SUM(CASE WHEN outcome = 'app_opened' THEN 1 ELSE 0 END) AS app_opens,
ROUND(SUM(CASE WHEN outcome = 'app_opened' THEN 1 ELSE 0 END)::DECIMAL / COUNT(*) * 100, 1) AS open_rate,
SUM(CASE WHEN outcome = 'fallback' THEN 1 ELSE 0 END) AS fallbacks,
SUM(CASE WHEN outcome = 'store_redirect' THEN 1 ELSE 0 END) AS store_redirects,
SUM(CASE WHEN converted THEN 1 ELSE 0 END) AS conversions,
ROUND(SUM(CASE WHEN converted THEN 1 ELSE 0 END)::DECIMAL / NULLIF(SUM(CASE WHEN outcome = 'app_opened' THEN 1 ELSE 0 END), 0) * 100, 1) AS conversion_rate
FROM deep_link_clicks
WHERE timestamp >= NOW() - INTERVAL '30 days'
GROUP BY country
ORDER BY clicks DESC
LIMIT 20;
Example output:
| Country | Clicks | App Opens | Open Rate | Fallbacks | Conversions | Conv. Rate |
|---|---|---|---|---|---|---|
| US | 25,000 | 18,750 | 75% | 4,250 | 2,812 | 15.0% |
| UK | 8,000 | 5,600 | 70% | 1,680 | 784 | 14.0% |
| Germany | 5,500 | 3,575 | 65% | 1,375 | 393 | 11.0% |
| India | 4,200 | 2,520 | 60% | 1,260 | 176 | 7.0% |
| Brazil | 3,800 | 2,280 | 60% | 1,140 | 205 | 9.0% |
Observations:
- US has the highest open rate (75%) and conversion rate (15%).
- India has a low open rate (60%), likely because many users do not have the app installed yet.
- Germany's lower open rate (65%) may relate to Android-heavy market and App Links configuration issues.
City-Level Performance
City-level data is useful for geo-targeted campaigns and events:
SELECT
city,
country,
COUNT(*) AS clicks,
ROUND(SUM(CASE WHEN outcome = 'app_opened' THEN 1 ELSE 0 END)::DECIMAL / COUNT(*) * 100, 1) AS open_rate
FROM deep_link_clicks
WHERE campaign = 'event-conference-2026'
AND timestamp >= '2026-07-15'
GROUP BY city, country
ORDER BY clicks DESC
LIMIT 10;
Geographic Segmentation
Tier-Based Segmentation
Group countries by market maturity and deep link behavior:
| Tier | Countries | Strategy |
|---|---|---|
| Tier 1 (mature, high-value) | US, UK, Canada, Australia, Germany, France, Japan | Full optimization, both platforms |
| Tier 2 (growing, medium-value) | Brazil, Mexico, India, Indonesia, Turkey | Android-focused, deferred deep links important |
| Tier 3 (emerging, lower-value) | Nigeria, Bangladesh, Vietnam, Pakistan | Mobile web focus, app install campaigns |
Campaign Targeting by Geography
{
"campaign": "summer-savings-2026",
"targeting": {
"tier_1": {
"deep_link": "https://links.app.com/offers/summer-savings",
"fallback": "https://app.com/offers/summer-savings",
"channels": ["email", "push", "paid_social"]
},
"tier_2": {
"deep_link": "https://links.app.com/offers/summer-savings",
"fallback": "https://app.com/offers/summer-savings",
"channels": ["email", "push"]
},
"tier_3": {
"deep_link": null,
"web_link": "https://app.com/offers/summer-savings",
"channels": ["email"]
}
}
}
Implementation
IP-Based Geolocation
Most deep link platforms determine geography from the user's IP address using databases like MaxMind GeoLite2:
import maxmind from 'maxmind';
async function getGeoData(ip: string): Promise<GeoData> {
const lookup = await maxmind.open('/path/to/GeoLite2-City.mmdb');
const result = lookup.get(ip);
return {
country: result?.country?.iso_code || 'unknown',
region: result?.subdivisions?.[0]?.iso_code || 'unknown',
city: result?.city?.names?.en || 'unknown',
latitude: result?.location?.latitude,
longitude: result?.location?.longitude,
timezone: result?.location?.time_zone
};
}
Geographic Dashboard Visualization
interface GeoChartData {
countries: {
code: string;
name: string;
clicks: number;
openRate: number;
conversionRate: number;
color: string; // Based on metric intensity
}[];
}
function buildChoroplethData(clicks: ClickData[]): GeoChartData {
const byCountry = groupBy(clicks, 'country');
return {
countries: Object.entries(byCountry).map(([code, countryClicks]) => ({
code,
name: countryNames[code],
clicks: countryClicks.length,
openRate: countryClicks.filter(c => c.outcome === 'app_opened').length / countryClicks.length,
conversionRate: countryClicks.filter(c => c.converted).length / countryClicks.length,
color: getHeatColor(countryClicks.length)
}))
};
}
Optimizing by Geography
Localized Fallback Pages
When a deep link falls back to the web, show a localized page:
function getFallbackUrl(deepLink: string, country: string, language: string): string {
const baseUrl = 'https://app.com';
const path = new URL(deepLink).pathname;
// Localized content
const localizedPath = `/${language}${path}`;
// Country-specific app store link
const storeLink = getAppStoreLink(country);
return `${baseUrl}${localizedPath}?store=${encodeURIComponent(storeLink)}`;
}
Country-Specific Deep Link Behavior
function handleDeepLinkByCountry(click: ClickEvent): string {
switch (click.country) {
case 'CN':
// China: Redirect to Huawei AppGallery or direct APK
return getChineseStoreLink(click.platform);
case 'RU':
// Russia: Check for alternative stores
return getRussianStoreLink(click.platform);
default:
// Standard: Google Play or Apple App Store
return getStandardStoreLink(click.platform, click.country);
}
}
Privacy and Geographic Data
GDPR Considerations
Under GDPR, IP-based geolocation is considered personal data processing. You need a legal basis (legitimate interest or consent) to collect and store geographic data from EU users.
- Aggregate geographic data (country-level click counts) is generally lower risk.
- City-level or latitude/longitude data is more sensitive and may require explicit consent.
- IP addresses should be anonymized after geolocation lookup (truncate the last octet).
Tolinku for Geographic Analytics
Tolinku's analytics include geographic breakdowns using MaxMind GeoLite2 IP geolocation. View clicks by country, region, and city in the Tolinku dashboard. Filter analytics by geography to compare campaign performance across markets.
For device analytics, see device analytics: optimizing deep links by platform. For deep link analytics, see deep link analytics: measuring what matters.
Get deep linking tips in your inbox
One email per week. No spam.