Messaging channels: a taxi and a food app are no longer a country's top messaging app

The classifier matched "line" as a bare word, so "LINE MAN: Food Delivery & more"
(Thailand) and "Malé Taxi Line" (Maldives) each ranked as the country's top messaging
app, ahead of WhatsApp. LINE now matches only as the whole name or before a colon.

The classifier moves to app-kind.mjs so the fetcher and the table builder share it,
and the builder re-derives each kind from the app name, so a cached fetch made under
an older rule cannot carry its answer forward. The headline count is computed from
the rows instead of typed: WhatsApp (Messenger or Business) is top in 73 countries.
This commit is contained in:
Doxa Maps 2026-09-27 01:51:07 +00:00
parent f728831d77
commit 1801bbc20f
7 changed files with 58 additions and 133 deletions

View file

@ -2,7 +2,7 @@
"meta": {
"title": "Messaging & App Channels",
"grain": "one row per country x communication app",
"why": "Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp is the top messaging app in 54 countries, Telegram in 38 — neither appears in referral share at all.",
"why": "Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp (Messenger or Business) is the top messaging app in 73 countries, Telegram in 38 — neither appears in referral share at all.",
"ios_caveat": "iOS ONLY. Most of these countries are Android-majority and Google publishes no keyless equivalent, so this is one eye open. An app absent here is NOT absent in-country. 50 of 175 countries have no Apple storefront.",
"ranking_caveat": "A top-free RANK is most-DOWNLOADED recently, not most-used.",
"classification_caveat": "kind is a name-keyword HEURISTIC over a known list, not a verified taxonomy.",
@ -2830,19 +2830,6 @@
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Thailand",
"iso3": "THA",
"region": "Asia",
"app": "LINE MAN: Food Delivery & more",
"kind": "messaging",
"rank": 13,
"is_top_messaging": true,
"people_groups": 8,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Burkina Faso",
"iso3": "BFA",
@ -3006,7 +2993,7 @@
"app": "WhatsApp Messenger",
"kind": "messaging",
"rank": 37,
"is_top_messaging": false,
"is_top_messaging": true,
"people_groups": 8,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
@ -7809,19 +7796,6 @@
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Maldives",
"iso3": "MDV",
"region": "Asia",
"app": "Malé Taxi Line",
"kind": "messaging",
"rank": 1,
"is_top_messaging": true,
"people_groups": 1,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Northern Mariana Islands",
"iso3": "MNP",
@ -13120,7 +13094,7 @@
"app": "WhatsApp Messenger",
"kind": "messaging",
"rank": 33,
"is_top_messaging": false,
"is_top_messaging": true,
"people_groups": 1,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",

View file

@ -0,0 +1,26 @@
// app-kind.mjs — what KIND of communication channel an App Store app is, from its name.
//
// A NAME-AND-KEYWORD HEURISTIC over a known list, recorded as such in every table that uses it.
// It lives in its own file so the fetcher (fetch-top-apps.mjs) and the table builder
// (build-tabulator-tables.mjs) classify with the SAME rule: the builder re-derives the kind from
// the stored name, so a cached fetch made with an older rule cannot carry an old answer forward.
//
// ★ A BRAND THAT IS ALSO AN ENGLISH WORD MUST BE ANCHORED. `line` matched as a bare word made
// "LINE MAN: Food Delivery & more" (Thailand) and "Malé Taxi Line" (Maldives) each country's TOP
// messaging app, ahead of WhatsApp. LINE's own app is "LINE" or "LINE: Calls & Messages", so it
// matches only as the whole name or the name before a colon.
export const KIND = [
[/\b(whatsapp|telegram|signal|viber|imo|zalo|wechat|weixin|kakaotalk|botim|imessage|messenger|skype|hike|jio ?chat|soul|beetalk)\b|^line(?:$|\s*:)/i, 'messaging'],
[/\b(tiktok|douyin|kwai|likee|snack ?video|moj|josh|triller|reels)\b/i, 'short-video'],
[/\b(facebook|instagram|snapchat|x|twitter|threads|vk|odnoklassniki|weibo|qzone|xiaohongshu|little red|sharechat|koo|mastodon|bluesky)\b/i, 'social'],
[/\b(youtube|bigo|nimo|twitch|rumble|dailymotion|vimeo)\b/i, 'video'],
[/\b(opera|uc ?browser|chrome|firefox|brave|puffin|phoenix ?browser)\b/i, 'browser'],
];
export function classify(name) {
for (const [re, k] of KIND) if (re.test(String(name || '').trim())) return k;
return 'other';
}
// The kinds a reachability table keeps (everything else is not a communication channel).
export const isComms = (kind) => kind !== 'other' && kind !== 'browser';

View file

@ -28,6 +28,7 @@
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join, resolve } from 'node:path';
import { classify, isComms } from './app-kind.mjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const OUT = join(__dirname, 'out');
@ -553,6 +554,15 @@ if (has('social-platforms-by-country.json')) {
}
}
// The headline counts are COUNTED from the rows, never typed: a typed "54" stayed true only until
// the classifier changed. WhatsApp is its two apps (Messenger + Business) together.
function messagingWhy(rows) {
const top = new Map();
for (const r of rows) if (r.is_top_messaging) top.set(r.iso3, r.app);
const count = (re) => [...top.values()].filter((a) => re.test(a)).length;
return `Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp (Messenger or Business) is the top messaging app in ${count(/whatsapp/i)} countries, Telegram in ${count(/telegram/i)} — neither appears in referral share at all.`;
}
// ═══ TABLE 7 — MESSAGING & APP CHANNELS (what referral stats cannot see) ═══
// StatCounter's ENTIRE tracked universe is Western referral platforms — measured:
// Facebook/Instagram/Twitter/YouTube/Pinterest/reddit/LinkedIn/Tumblr/HN/VK/Fark.
@ -572,7 +582,11 @@ if (has('top-apps-by-country.json')) {
for (const c of Object.values(apps.countries)) {
const meta = g[c.iso3] || {};
// One row per COUNTRY x APP so a list view can sort "where does Telegram rank".
for (const a of (c.comms_apps || [])) {
// The kind is RE-DERIVED from the name with the shared classifier (app-kind.mjs), and the top
// messaging app with it: the cached fetch may carry a kind from an older rule.
const comms = (c.comms_apps || []).map((a) => ({ ...a, kind: classify(a.name) })).filter((a) => isComms(a.kind));
const topMessaging = comms.slice().sort((x, y) => x.rank - y.rank).find((a) => a.kind === 'messaging')?.name || null;
for (const a of comms) {
rows.push({
country: meta.country || c.iso3,
iso3: c.iso3,
@ -580,7 +594,7 @@ if (has('top-apps-by-country.json')) {
app: a.name,
kind: a.kind,
rank: a.rank,
is_top_messaging: a.name === c.top_messaging,
is_top_messaging: a.name === topMessaging,
people_groups: meta.groups || 0,
platform_bias: c.platform_bias,
classification: c.classification_method,
@ -605,7 +619,7 @@ if (has('top-apps-by-country.json')) {
], {
title: 'Messaging & App Channels',
grain: 'one row per country x communication app',
why: 'Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp is the top messaging app in 54 countries, Telegram in 38 — neither appears in referral share at all.',
why: messagingWhy(rows),
ios_caveat: 'iOS ONLY. Most of these countries are Android-majority and Google publishes no keyless equivalent, so this is one eye open. An app absent here is NOT absent in-country. 50 of 175 countries have no Apple storefront.',
ranking_caveat: 'A top-free RANK is most-DOWNLOADED recently, not most-used.',
classification_caveat: 'kind is a name-keyword HEURISTIC over a known list, not a verified taxonomy.',

View file

@ -40,6 +40,7 @@
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { classify, isComms } from './app-kind.mjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const OUT = join(__dirname, 'out');
@ -55,19 +56,7 @@ const SOURCE = {
why: 'StatCounter tracks only Western referral platforms and cannot see WhatsApp/WeChat/Telegram/TikTok/LINE/Viber/imo/Zalo — the channels that dominate most of this corpus',
};
// Known non-Western + messaging platforms worth surfacing explicitly. Matching is
// a HEURISTIC on the app name; recorded as such.
const KIND = [
[/\b(whatsapp|telegram|signal|viber|imo|line|zalo|wechat|weixin|kakaotalk|botim|imessage|messenger|skype|hike|jio ?chat|soul|beetalk)\b/i, 'messaging'],
[/\b(tiktok|douyin|kwai|likee|snack ?video|moj|josh|triller|reels)\b/i, 'short-video'],
[/\b(facebook|instagram|snapchat|x|twitter|threads|vk|odnoklassniki|weibo|qzone|xiaohongshu|little red|sharechat|koo|mastodon|bluesky)\b/i, 'social'],
[/\b(youtube|bigo|nimo|twitch|rumble|dailymotion|vimeo)\b/i, 'video'],
[/\b(opera|uc ?browser|chrome|firefox|brave|puffin|phoenix ?browser)\b/i, 'browser'],
];
const classify = (name) => {
for (const [re, k] of KIND) if (re.test(name)) return k;
return 'other';
};
// The classifier (KIND / classify) is shared with build-tabulator-tables.mjs: see app-kind.mjs.
const ISO2 = existsSync(join(OUT, 'iso3-to-iso2.json'))
? JSON.parse(readFileSync(join(OUT, 'iso3-to-iso2.json'), 'utf8'))
@ -113,7 +102,7 @@ for (let n = 0; n < todo.length; n++) {
}
} catch (e) { err = String(e.message || e).slice(0, 60); }
const comms = apps.filter((a) => a.kind !== 'other' && a.kind !== 'browser');
const comms = apps.filter((a) => isComms(a.kind));
out[iso3] = {
iso3, iso2: ISO2[iso3],
apps: apps.slice(0, 25),

View file

@ -2,7 +2,7 @@
"meta": {
"title": "Messaging & App Channels",
"grain": "one row per country x communication app",
"why": "Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp is the top messaging app in 54 countries, Telegram in 38 — neither appears in referral share at all.",
"why": "Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp (Messenger or Business) is the top messaging app in 73 countries, Telegram in 38 — neither appears in referral share at all.",
"ios_caveat": "iOS ONLY. Most of these countries are Android-majority and Google publishes no keyless equivalent, so this is one eye open. An app absent here is NOT absent in-country. 50 of 175 countries have no Apple storefront.",
"ranking_caveat": "A top-free RANK is most-DOWNLOADED recently, not most-used.",
"classification_caveat": "kind is a name-keyword HEURISTIC over a known list, not a verified taxonomy.",
@ -2830,19 +2830,6 @@
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Thailand",
"iso3": "THA",
"region": "Asia",
"app": "LINE MAN: Food Delivery & more",
"kind": "messaging",
"rank": 13,
"is_top_messaging": true,
"people_groups": 8,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Burkina Faso",
"iso3": "BFA",
@ -3006,7 +2993,7 @@
"app": "WhatsApp Messenger",
"kind": "messaging",
"rank": 37,
"is_top_messaging": false,
"is_top_messaging": true,
"people_groups": 8,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
@ -7809,19 +7796,6 @@
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Maldives",
"iso3": "MDV",
"region": "Asia",
"app": "Malé Taxi Line",
"kind": "messaging",
"rank": 1,
"is_top_messaging": true,
"people_groups": 1,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Northern Mariana Islands",
"iso3": "MNP",
@ -13120,7 +13094,7 @@
"app": "WhatsApp Messenger",
"kind": "messaging",
"rank": 33,
"is_top_messaging": false,
"is_top_messaging": true,
"people_groups": 1,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",

View file

@ -2,7 +2,7 @@
"meta": {
"title": "Messaging & App Channels",
"grain": "one row per country x communication app",
"why": "Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp is the top messaging app in 54 countries, Telegram in 38 — neither appears in referral share at all.",
"why": "Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp (Messenger or Business) is the top messaging app in 73 countries, Telegram in 38 — neither appears in referral share at all.",
"ios_caveat": "iOS ONLY. Most of these countries are Android-majority and Google publishes no keyless equivalent, so this is one eye open. An app absent here is NOT absent in-country. 50 of 175 countries have no Apple storefront.",
"ranking_caveat": "A top-free RANK is most-DOWNLOADED recently, not most-used.",
"classification_caveat": "kind is a name-keyword HEURISTIC over a known list, not a verified taxonomy.",
@ -2830,19 +2830,6 @@
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Thailand",
"iso3": "THA",
"region": "Asia",
"app": "LINE MAN: Food Delivery & more",
"kind": "messaging",
"rank": 13,
"is_top_messaging": true,
"people_groups": 8,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Burkina Faso",
"iso3": "BFA",
@ -3006,7 +2993,7 @@
"app": "WhatsApp Messenger",
"kind": "messaging",
"rank": 37,
"is_top_messaging": false,
"is_top_messaging": true,
"people_groups": 8,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
@ -7809,19 +7796,6 @@
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Maldives",
"iso3": "MDV",
"region": "Asia",
"app": "Malé Taxi Line",
"kind": "messaging",
"rank": 1,
"is_top_messaging": true,
"people_groups": 1,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Northern Mariana Islands",
"iso3": "MNP",
@ -13120,7 +13094,7 @@
"app": "WhatsApp Messenger",
"kind": "messaging",
"rank": 33,
"is_top_messaging": false,
"is_top_messaging": true,
"people_groups": 1,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",

View file

@ -2,7 +2,7 @@
"meta": {
"title": "Messaging & App Channels",
"grain": "one row per country x communication app",
"why": "Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp is the top messaging app in 54 countries, Telegram in 38 — neither appears in referral share at all.",
"why": "Referral stats (StatCounter) structurally cannot see messaging apps. Measured here: WhatsApp (Messenger or Business) is the top messaging app in 73 countries, Telegram in 38 — neither appears in referral share at all.",
"ios_caveat": "iOS ONLY. Most of these countries are Android-majority and Google publishes no keyless equivalent, so this is one eye open. An app absent here is NOT absent in-country. 50 of 175 countries have no Apple storefront.",
"ranking_caveat": "A top-free RANK is most-DOWNLOADED recently, not most-used.",
"classification_caveat": "kind is a name-keyword HEURISTIC over a known list, not a verified taxonomy.",
@ -2830,19 +2830,6 @@
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Thailand",
"iso3": "THA",
"region": "Asia",
"app": "LINE MAN: Food Delivery & more",
"kind": "messaging",
"rank": 13,
"is_top_messaging": true,
"people_groups": 8,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Burkina Faso",
"iso3": "BFA",
@ -3006,7 +2993,7 @@
"app": "WhatsApp Messenger",
"kind": "messaging",
"rank": 37,
"is_top_messaging": false,
"is_top_messaging": true,
"people_groups": 8,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
@ -7809,19 +7796,6 @@
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Maldives",
"iso3": "MDV",
"region": "Asia",
"app": "Malé Taxi Line",
"kind": "messaging",
"rank": 1,
"is_top_messaging": true,
"people_groups": 1,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",
"source": "Apple App Store RSS — top free apps by country"
},
{
"country": "Northern Mariana Islands",
"iso3": "MNP",
@ -13120,7 +13094,7 @@
"app": "WhatsApp Messenger",
"kind": "messaging",
"rank": 33,
"is_top_messaging": false,
"is_top_messaging": true,
"people_groups": 1,
"platform_bias": "iOS only — most of these countries are Android-majority; absence here is not absence in-country",
"classification": "name-keyword HEURISTIC, not a verified taxonomy",