# Deterministic attribution, and why GHAN refuses fingerprinting

> GHAN attributes an install only when a single-use, unexpired, signed token is presented by the receiving app and countersigned with its own key. There is no fingerprinting fallback, and an install that cannot prove itself is simply not attributed.

Source: https://ghan.io/attribution/  
Published: 2026-09-22 · Updated: 2026-09-22  
Publisher: GHAN — the audited cross-promotion network for desktop apps (https://ghan.io)

---

## The rule

> An install is attributed if and only if a single-use, unexpired, server-signed token is presented by the receiving SDK and countersigned with that SDK's own ed25519 key. There is no second mechanism.

Everything below is the consequence of that sentence.

## The token

| Property | Value | Enforced by |
|---|---|---|
| Issued at | Click time, server side | `tokens` table row |
| Lifetime | 15 minutes | `expires_at`, checked server side |
| Uses | Exactly one | Unique constraint on `used_at` |
| Nonce | Per token | Column, generated server side |
| Binding | Campaign + serving app | Foreign keys on the token row |

Single use is enforced by a database constraint, not by an `if` statement, because an `if` statement has a race condition and a unique index does not.

## The two signatures

A GHAN event carries up to three signatures, and the monetised transition requires two of them to be independent:

- `sig_serving` — produced by the SDK inside the app that rendered the card
- `sig_receiving` — produced by the SDK inside the app that was installed
- `server_sig` — produced by GHAN, which proves GHAN saw it, and proves nothing about whether it happened

A chain cannot advance past `install_claim` without both `sig_serving` and `sig_receiving`. Neither app can produce the other's signature, because each private key was generated on the end user's machine on first run and never left it.

This is the structural reason GHAN's numbers are checkable: for any install you were billed for, you personally hold one of the two signatures that made it billable.

## What GHAN deliberately gives up

Refusing probabilistic attribution is not free. It costs:

- **Attributed volume.** Installs that took the long route are invisible, and the serving app earns nothing for them.
- **Cross-device journeys.** Download on a work laptop, install on a home machine, and the chain correctly does not exist.
- **Comparability.** A mobile MMP will report higher attribution rates than GHAN for the same traffic, because it is counting things GHAN refuses to count.

The alternative is a network where the easiest way to earn is to make weak signals look strong. Every monetised feature in GHAN has to pass one test — the cost of faking it must exceed the payout for it — and a probabilistic fallback fails that test on the first line.

## What is collected, and what is not

Attached to an install claim:

- Virtual machine and hypervisor indicators
- Operating-system install age
- A **salted** hardware hash, never the raw identifier
- Clock skew against the server
- The claiming IP's country and autonomous system, resolved from an offline database so the address itself never leaves GHAN's infrastructure on the hot path

Not collected, ever:

- File names, file contents, window titles, clipboard, keystrokes
- Raw hardware identifiers, MAC addresses, serial numbers
- Advertising identifiers or any cross-app identity
- Any personally identifying information at all

The device signals exist to kill fraudulent chains, not to identify people, and they are strictly worse at identifying people than the fingerprinting GHAN refuses to do. That is the intended ordering.

## Consent

The SDK ships a consent-safe mode. The host application passes its own consent state, and no telemetry at all is emitted before consent is true. A GHAN card can still render — rendering a templated card is not processing personal data — but nothing is measured until the person has agreed to measurement. See [security and privacy](/security/).

## Questions people ask about this

### What is deterministic attribution?

Deterministic attribution means an install is credited to a source only when a unique identifier issued at click time is presented back at install time and verified. The alternative, probabilistic attribution, infers the match from signals like IP address, screen resolution, operating system version and timing. Deterministic attribution either proves the link or admits it cannot; probabilistic attribution always produces an answer, including when there is nothing to find.

### Why not use fingerprinting as a fallback?

Because a fallback is not a safety net, it is the attack surface. The moment a network will credit an install on IP-plus-timestamp similarity, the cheapest way to earn is to generate plausible similarity at scale, and every fraud rule downstream is then arguing with a system that was designed to say yes. Refusing the fallback costs GHAN attributable volume and buys the one property the network is sold on.

### How does the token survive a browser download and a manual install?

Two paths, both deterministic. The click registers a ghan:// protocol handler invocation carrying the token, and the same token is written to a small handoff file in a known location. The receiving SDK checks both on first run. If a person downloads on one machine and installs on another, neither path finds the token and the install is correctly not attributed.

### What is the token expiry and why 15 minutes?

Fifteen minutes from issue, enforced server-side, with single use enforced by a unique constraint in the database rather than by application logic. Fifteen minutes is long enough for a normal download-and-install on a normal connection and short enough that a harvested token is worthless by the time it could be resold.

### What percentage of installs go unattributed?

GHAN expects a meaningful share of real installs to go unattributed - people who download now and install tomorrow, people who move the installer to another machine, people behind restrictive protocol-handler policies. Those installs are free for the advertiser and earn the serving app nothing. Undercounting is the deliberate side of the trade.

