familiewapen Mick Beermickbeer.com

manuscript · Real-time bidding

beginselessayReal-time biddingverwant

Je toestelprofiel is de hoofdmoot van wat een app verstuurt

Bij gratis Nederlandse apps vertrekt bij het laden van een advertentie een OpenRTB-biedverzoek met het reclamenummer, de locatie, de netwerkcode, de provider en de toestemmingsstring erin. Dat verzoek gaat naar elke partij die op het veilingplatform mag meebieden, dus ook naar iedereen die verliest. In één gebruikssessie ging 87 procent van de netwerkverzoeken en 54 procent van de bytes naar de advertentieketen. Onverwante apps blijken dezelfde kopers achter zich te hebben: van zeven bieders in een echte bid-respons stonden er zes ook in de partnerlijst van een totaal andere app. Wat ik meet is het vertrek; wat er daarna tussen servers gebeurt blijft buiten beeld, dus elk getal is een ondergrens.

Wat een biedstroom is

Je opent een gratis app. Voordat er iets op je scherm staat, meldt de app dat er advertentieruimte vrij is. Dat bericht gaat naar een veilingplatform, een ad exchange. Dat platform stuurt het in een fractie van een seconde door naar de partijen die op dat platform mogen meebieden. De hoogste bieder wint, de advertentie laadt. Het hele proces duurt ongeveer honderd milliseconden.

Zo'n bericht heet een biedverzoek. De aanhoudende reeks ervan heet de biedstroom. Het protocol eronder heet OpenRTB, een open standaard van het IAB Tech Lab. De krappe timing staat in het verzoek zelf, in het veld tmax: de maximale tijd in milliseconden waarbinnen een bieder mag antwoorden. Wie te laat is, doet niet mee.

Tot hier is het techniek voor reclamemensen. Het wordt iets anders zodra je opent wat er in dat bericht meegaat. Zie Real-time bidding biedt jouw toestel in een veiling aan, in milliseconden.

Wat er precies in het verzoek staat

Een biedverzoek is een JSON-object. Het beschrijft de vrije advertentieplek, en het beschrijft je toestel. Een sterk versimpeld voorbeeld, in de vorm die de standaard voorschrijft:

{
  "id": "8b3e...c1",
  "at": 1,
  "tmax": 120,
  "imp": [{ "id": "1", "banner": { "w": 320, "h": 50 } }],
  "app": { "bundle": "com.voorbeeld.app", "name": "Voorbeeld" },
  "device": {
    "ifa": "38400000-8cf0-11bd-b23e-10b96e40000d",
    "ua": "Mozilla/5.0 ...",
    "ip": "84.29.xx.xx",
    "geo": { "lat": 52.09, "lon": 5.11, "type": 2 },
    "make": "Apple", "model": "iPhone", "os": "iOS"
  },
  "user": { "id": "abc", "buyeruid": "xyz" }
}

Elk veld is een stukje van jou. device.ifa is de identifier for advertisers, het reclamenummer van je telefoon. geo is een geschatte locatie, soms uit je IP-adres afgeleid, soms nauwkeuriger. device beschrijft je toestel tot op het model. app.bundle verklapt in welke app je zit, en dus vaak iets over je situatie op dat moment. user.buyeruid is de identifier die een koper eerder aan je heeft gehangen.

Dat de standaard deze velden kent, is gemeten: de OpenRTB-specificatie is openbaar en de veldnamen liggen vast. Welke velden een concrete app werkelijk invult, is per app afgeleid uit het echte biedverkeer.

Het reclamenummer heet resetbaar, en dat klinkt geruststellend. Zodra dezelfde waarde in elk verzoek meereist, werkt hij als koppelsleutel tussen bestemmingen. Zie Een resetbare identifier is alsnog een sleutel en Het reclamenummer is de sleutel die anoniem persoonlijk maakt.

Wat ik in Nederlandse apps heb gemeten

Ik heb de biedstroom van losse Nederlandse consumenten-apps onderschept en ontcijferd. Een weer-app, een handel-app, een woon-app, een ov-app. Bij Buienalarm en Marktplaats ving ik de biedaanvraag op die al bij het laden van de advertentie vertrekt. Daarin zaten het reclamenummer van de telefoon, de locatie, de netwerkcode en de provider. Het volledige toestelprofiel, voordat de gebruiker iets had aangeraakt. Zie Je toestelprofiel gaat de veiling in voor je iets aanraakt.

In een onderschepte en ontcijferde biedaanvraag van een weer-app zaten het advertentie-ID, land, netwerkcode, provider, taal, locatie en de toestemmingsstring. Er zit geen afweging per veld in. Die velden vertrekken samen, in één keer. Anonimiseren gebeurt onderweg niet. Zie Je hele toestelprofiel gaat in een keer de veiling in.

Dan de verhouding. In één gebruikssessie ging 87 procent van de netwerkverzoeken en 54 procent van de bytes naar de advertentieketen, tegen een fractie echt verkeer. Dat is één sessie op één app, en ik presenteer het als zodanig. Het gevolg is wel concreet: je databundel en je batterij betalen grotendeels aan een laag die jou niets oplevert. Zie Het meeste verkeer van je app gaat niet naar de app.

Weinig advertentieverkeer is trouwens geen vrijbrief. Een ov-app met ongeveer één procent advertentieverkeer stond toch in een gelekte databrokerlijst. Eén partner in de keten is genoeg. Zie Ook een schone app kan in de databrokerlijst staan.

Waarom verliezen niets kost

Hier zit de kern die de meeste mensen missen. Het biedverzoek gaat niet naar één koper. Het wordt uitgezonden naar iedere partij die op dat veilingplatform mag meebieden. Tientallen bedrijven ontvangen dus dezelfde JSON met jouw kenmerken erin. Precies één van hen wint. De rest verliest en houdt de data.

Een partij hoeft de plek dus niet te winnen om je gegevens te krijgen. Meebieden mogen is genoeg. Verliezen kost niets en levert wel een compleet profielsignaal op: identifier, grove locatie, toestel, app, tijdstip. Dat gedrag heeft in de sector een naam, bid stream data harvesting. Dat het technisch mogelijk is, volgt rechtstreeks uit hoe het protocol uitzendt en is dus afgeleid. Hoe vaak een specifieke partij het doet, blijft zonder inzage in hun systemen vermoed.

Eén advertentieplek op je scherm staat daarmee gelijk aan tientallen partijen die je profiel te zien kregen. Een privacyverklaring laat één plek meestal klinken als één adverteerder.

De volgorde is bovendien omgekeerd aan wat je verwacht. Eerst gaat je profiel de markt op, dan bieden partijen, dan pas wordt beslist wat je te zien krijgt. Het aantal partijen dat je profiel zag, staat los van het aantal advertenties dat je kreeg. Zie Een biedstroom kan een veiling ingaan waar buitenlandse partijen op meebieden.

Dezelfde kopers achter apps die niets met elkaar te maken hebben

Toen ik de lijsten per app naast elkaar legde, kwam er een overlap boven die ik niet zocht. Apps van verschillende makers, voor verschillende doelen, hadden dezelfde advertentie-infrastructuur achter zich. Eén verkoopplatform en een handjevol vaste bieders.

In een echte bid-respons uit één app zaten zeven biedende partijen. Zes daarvan staan ook in de partnerlijst van een totaal andere app. De namen die keer op keer terugkomen zijn PubMatic, Magnite, Criteo en Index Exchange. Bewijsniveau: gemeten. De zeven komen uit een echte bid-respons, de zes overlappende uit de partnerlijst van de andere app.

Een enkele overlap kan toeval zijn. Zes van de zeven, dwars door onverwante apps heen, is het patroon zelf. De app levert de gelegenheid, de markt levert de kopers. Zie Onverwante apps sturen je profiel dezelfde veiling in.

Dat heeft een gevolg voor het idee dat je per app kunt kiezen. De toestemmingsvraag staat in de app en geldt voor die app. De veiling erachter is gedeeld. De partij die je in de ene app weigert, ziet je in de volgende alsnog, via dezelfde veiling waarop die volgende app is aangesloten.

Achter die markt zit bovendien een kleine, vaste groep locatie-databrokers die via meegeleverde SDK's de positie van toestellen verzamelt en doorverkoopt. In een index van honderden apps kwamen steeds dezelfde namen terug: X-Mode, inmiddels Outlogic en met een FTC-verbod, Gravy/Venntel, dat locatiedata aan Amerikaanse overheden leverde, plus OneAudience, Sense360, SignalFrame, Fysical, Placed en Predicio. Zie De locatiedatahandel draait op een handvol vaste spelers.

Waar mijn meting ophoudt

Dit hoort erbij, anders is het cijfer meer waard dan het is.

Ik meet het vertrek. Ik leg het netwerkverkeer van een app vast, vis de biedverzoeken eruit en lees welke van mijn kenmerken meegaan. Wat er daarna tussen servers gebeurt, valt buiten beeld. Een exchange kan een verzoek doorverkopen aan een andere exchange. Een winnende bieder kan het profiel intern delen. Elk getal dat ik noem is daarom een ondergrens. Zie Elke browsermeting is een ondergrens en Label elke bevinding op bewijsniveau.

De meting kan ook stuklopen op de app zelf. Bij de Funda-app brak een patch op het toestel alleen het slot aan de kant van de app. De server gaf een foutmelding en de echte biedstroom bleef ongezien. Dat het advertentie-ID meegaat de biedstroom in, is daar statisch aangetoond in de code. De live capture kwam nooit rond. Statisch bewijs en live bewijs zijn twee verschillende niveaus, en dat verschil hoort in het rapport. Zie in de code gevonden is niet hetzelfde als live gemeten en Je advertentie-ID gaat ongefilterd de veiling in.

Twee valkuilen bewaak ik daarnaast streng. Een naam in ads.txt betekent dat een systeem de ruimte mág verhandelen, wat iets anders is dan een waargenomen stroom. Zie Een advertentiesysteem mag meeverkopen zonder ooit een bod te doen. En een uitgewisseld herkenningsnummer bewijst herkenning. Op een grote nieuwssite wisselde een advertentiebedrijf in 82 geschikte videoveilingen, verdeeld over 48 sessies en drie dagdelen, telkens een nummer uit zonder ook maar één keer te bieden. De koppeling was er, het bod nul keer. Zie Een cookie-match bewijst herkenning, geen bod en niet gezien is geen bewijs van afwezigheid.

Wat dit juridisch betekent

Onder de AVG is een reclame-identifier een persoonsgegeven, want hij maakt je herkenbaar. Het uitzenden ervan naar tientallen ontvangers is een verwerking, en elke ontvanger is een eigen partij in de zin van de wet. De rechtsgrond is vrijwel altijd toestemming, geregeld via het IAB TCF, het Transparency and Consent Framework. Dat framework codeert je keuzes in een consent string die met het biedverzoek meereist.

Het probleem is dat de gegeven toestemming zelden dekt wat er feitelijk gebeurt. Je stemt in met een lijst partners die je op een muur te zien kreeg, terwijl de biedstroom breder gaat dan die muur. Zie De cookiemuur toont minder partners dan de code telt. De keten achter de exchange, met resellers en tussenpartijen, staat in geen enkele verklaring. Zie De advertentieketen heeft schakels die niemand in de verklaring noemt. De Belgische toezichthouder oordeelde in 2022 dat het TCF zoals het toen werkte in strijd was met de AVG, onder meer omdat de consent string zelf een persoonsgegeven is dat zonder geldige grond werd verspreid.

Daarmee is bij RTB "waar staat de server" de verkeerde vraag. De juiste vraag is wie er mag meekijken in de veiling, en dat is een bredere en internationalere groep dan de app zelf noemt. Zodra het biedverzoek partijen buiten de EER bereikt, is er doorgifte naar een derde land, waar hoofdstuk V van de AVG eisen aan stelt. Zie Waar het pakket landt en wie het kan vorderen zijn twee assen.

Eén waarschuwing over het alternatief dat als oplossing wordt aangeboden. Een grote app declareert de nieuwe Privacy Sandbox Topics- en Attribution-rechten én het klassieke advertentie-ID, gewoon naast elkaar. Het privacyvriendelijke signaal komt er dus bovenop. Zie De privacyvriendelijke opvolger komt naast het oude tracken.

Wat je hier morgen mee doet

Als lezer, in vijf minuten. Zet op Android het reclamenummer uit via Instellingen, Privacy, Advertenties, en kies daar Advertentie-ID verwijderen. Op iOS zet je onder Privacy en beveiliging de tracking-toestemming uit. Dat sluit de veiling niet, en het haalt wel het meest bruikbare koppelveld uit het verzoek. Zet daarna per app de locatiepermissie op "alleen tijdens gebruik", of helemaal uit bij apps die je positie niet nodig hebben.

Als je een keuze hebt tussen apps, kies de app zonder advertentielaag, ook als je ervoor betaalt. Een app die volledig lokaal werkt bestaat echt, en bewijst dat de zware advertentiestack een keuze is. Zie Een app kan volledig lokaal, zonder een enkele netwerkcall en Geen internet-permissie, geen probleem.

Als onderzoeker of functionaris gegevensbescherming: leg het netwerkverkeer van je eigen app vast en filter op de OpenRTB-signatuur, de combinatie van imp, device, at en tmax. Kijk vervolgens welke velden je app invult in device en user. Loop daarna de app-ads.txt van de uitgever en de sellers.json van de aangesloten exchanges door, en tel hoeveel deelnemers buiten de EER vallen. Noem dat getal een ondergrens, want dat is het.

En als bestuurder van een app die dit draait: een verklaring die stelt dat gegevens binnen de EU blijven, is bij een actieve RTB-integratie moeilijk waar te maken. Het kan technisch wel, met een besloten opstelling en een gecontroleerde deelnemerslijst. Dan is het een keuze die je in de configuratie ziet staan. De code wint van de verklaring, zoals altijd.

citeer alsBeer, M. (2026, 25 juli). Je toestelprofiel is de hoofdmoot van wat een app verstuurt. mickbeer.com. https://mickbeer.com/#je-toestelprofiel-is-de-hoofdmoot-van-wat-een-app-verstuurt

lees dit stuk in het manuscript, met alles waar het aan hangt