# 08 · Integration matrix — advertised vs. actually embedded (140 apps, 2026-06-28)

> Appmiral markets a long catalogue of [integrations](https://appmiral.com/features/integrations).
> This document checks that catalogue against reality: a static scan of **all 140
> installed apps** for the byte-signatures of each advertised integration (plus the
> common tracking SDKs the page omits), so we can see what every app **actually
> embeds** — and where the marketing and the binaries disagree.

Source data (this folder):
[`data/integration_matrix_2026-06-28.csv`](data/integration_matrix_2026-06-28.csv)
(app × integration matrix),
[`.identify.csv`](data/integration_matrix_2026-06-28.identify.csv) (per-app
versions/SDK/ABIs/perms), and
[`.json`](data/integration_matrix_2026-06-28.json) (every hit with the **exact
matched byte-pattern**, for audit). Scanner:
[`../../tools/apk-harvest/scan-integrations.py`](../../tools/apk-harvest/scan-integrations.py).

## Method (presence detection, auditable)

For each app the scanner concatenates the APK's `classes*.dex` + `resources.arsc`
+ native `.so` library names + `AndroidManifest` component/permission names, then
searches for ASCII substrings characteristic of each integration (package prefixes
like `com/crowdconnected`, `com/mapbox`, `com/permutive`; hostnames like
`crowdconnected.com`; SDK class/resource names). It is **presence-only** and
**records the matched pattern** for every hit, so any result can be re-checked.
Heavy R8/obfuscation can strip a literal package name (a **false negative**) — so
absence of a literal string is not proof of absence of capability; corroborate
location apps at runtime ([`09`](09-active-config-km-killswitch.md)).

## Counts across all 140 apps

| Integration | Apps /140 | Advertised? | Reading |
|---|---:|:--:|---|
| Instagram | 140 | ✓ | platform baseline |
| Firebase Analytics | 140 | — | **not on the integrations page** |
| Firebase Messaging | 140 | — | not on the page |
| Firebase Crashlytics | 140 | — | not on the page |
| Google Fused Location | 140 | — | location backbone; not on the page |
| YouTube | 139 | ✓ | platform baseline |
| AWS Cognito | 139 | ✓ | SSO / identity (CC auth) |
| CM.com | 139 | ✓ | platform baseline |
| Beatswitch | 139 | ✓ | platform baseline |
| **AWS Kinesis Firehose** | 139 | — | **the location egress pipe; not on the page** |
| Google Maps SDK | 139 | — | not on the page |
| Ticketmaster | 137 | ✓ | |
| Spotify | 128 | ✓ | |
| Get Moments | 114 | ✓ | |
| Facebook SDK | 52 | — | **not on the page** |
| OneTrust (consent) | 40 | — | consent management; not on the page |
| **Permutive** (CDP) | 36 | ✓ | variable adoption |
| **Mapbox** | 16 | ✓ | variable adoption |
| Billetten | 10 | ✓ | |
| **Crowd Connected** (literal) | 9 | ✓ | obfuscated away elsewhere — see below |
| Tealium | 2 | ✓ | |
| OpenID · Salesforce · Braze · OneSignal · Sentry | 1 each | mixed | long-tail |
| **TikTok, Azure, Sports Alliance, ShowPass, Eventim, Ticketpay, Tickoweb, Bleep, SeeTickets, WeezEvents, GET, Mobile Locker, Insider, Fanalist, PwC, Halo by CM, Inventis, Jebbit, Komo** | **0** | ✓ | **advertised but absent in every installed app (19 partners)** |

Location permissions (from `.identify.csv`): **all 140** request
`ACCESS_FINE_LOCATION` + `ACCESS_COARSE_LOCATION`; **30** additionally request
`ACCESS_BACKGROUND_LOCATION` (see
[`06-background-location-app-not-open.md`](06-background-location-app-not-open.md)).

## Three findings

### 1. "Advertised" over-states per-festival reality (platform baseline)

Every Appmiral app is built from one shared SDK/template, so a large set of
"integrations" is compiled into **~all 140 apps** regardless of whether a given
festival uses them (Instagram, YouTube, CM.com, Beatswitch, Ticketmaster, AWS
Cognito all sit at 137–140). The integrations page therefore reads as a **platform
superset**, not a per-app fact sheet. The signal that actually distinguishes apps
is the **variable-adoption** set — Permutive (36), Mapbox (16),
background-location (30), Crowd Connected literal (9), Tealium (2) — plus the
runtime config in [`09`](09-active-config-km-killswitch.md).

### 2. Advertised-but-absent: 19 partners in 0 installed apps

TikTok, Azure, Sports Alliance, ShowPass, Eventim, Ticketpay, Tickoweb, Bleep,
SeeTickets, WeezEvents, GET, Mobile Locker, Insider, Fanalist, PwC, Halo by CM,
Inventis, Jebbit and Komo are on the marketing page but match in **none** of the
140 installed apps. Some are server-side/web-only (ticketing back-ends, the PwC/Halo
"data partners"), some may be obfuscated, but the marketing list clearly does not
equal what ships in the Android binaries.

### 3. Present-but-not-advertised: the surveillance backbone is off the page

The integrations page foregrounds content/ticketing partners, but the components
that actually move attendee data are **not listed on it**:

- **AWS Kinesis Firehose (139/140)** — the egress pipe that streams Crowd Connected
  positions to `firehose.us-east-1` (see [`04`](04-live-capture-2026-06-26.md)).
- **Firebase Analytics / Messaging / Crashlytics (140 each)** and **Google Fused
  Location (140)** — analytics + the location source feeding the geofencing.
- **Facebook SDK (52)** and **OneTrust (40)** — a major ad/analytics SDK and a
  consent-management platform, neither acknowledged on the integrations page.

So the page both **over-claims** (19 absent partners) and **under-discloses** (the
Firehose/Firebase/Facebook/Fused-Location stack that does the data collection).

### The obfuscated Crowd Connected case

The literal `com.crowdconnected` package survives in only **9** apps, yet its
dependencies are near-universal: **AWS Cognito 139 + Kinesis Firehose 139 + Google
Fused Location 140**. The tracking **capability is bundled across essentially the
whole fleet**; obfuscation merely hides the brand string. This is why the
location-tracking cohort is far broader than the original hand-picked "12 apps,"
and why activation must be confirmed at runtime ([`09`](09-active-config-km-killswitch.md)).

## Reproduce

```powershell
python tools/apk-harvest/scan-integrations.py `
  --apks <private>/apks_2026-06-28_154246 `
  --out docs/appmiral-comparison/data/integration_matrix_2026-06-28
```

Full guide, pinned versions and expected output:
[`10-apk-harvest-reproduction.md`](10-apk-harvest-reproduction.md).
