How GHAN works
An install moves through GHAN as an event chain with six states. Each state transition requires cryptographic proof, money is held in escrow between claim and clearing, and any chain that cannot prove itself is refunded automatically rather than argued about.
The six states of an event chain
Every GHAN transaction is one row in event_chains that moves through a state machine. It can only move forward, and each move has a precondition that must be proven, not asserted.
| State | What has to be true to enter it |
|---|---|
impression | The serving SDK rendered a templated card and signed the render event |
click | The person clicked; a single-use token was issued with a 15-minute expiry |
install_claim | The receiving SDK found the token on first run and signed a claim with its own key |
activated_48h | 48 hours later the receiving app is still installed and has been used |
cleared | Escrow released, the serving app earned, the ledger line is final |
rejected | A fraud rule or a missing signature killed the chain; the hold is refunded |
A chain cannot advance past install_claim with a single signature. The serving app's signature proves the placement happened; the receiving app's signature proves the install happened. Neither party can produce the other's.
Step by step
1. The host app decides a moment has arrived
GHAN never decides when to interrupt someone. The host application calls ghan.slot('first_success') — or any of the other four lifecycle slots — at a moment it considers appropriate. If the host never calls, GHAN never renders.
2. The SDK fetches a signed placement
The server returns a signed placement payload: a partner app id, an icon URL, a name, and one generated line of copy. It never returns HTML, JavaScript or a custom image. The SDK renders the card itself in the host application's own UI layer, which is why a GHAN card cannot carry a payload.
3. The impression is signed and recorded
The SDK signs the impression with the ed25519 private key it generated on first run and stored in the app data directory. That key never leaves the machine; only the public key was ever registered.
4. A click issues a single-use token
If the person clicks, the server issues a token with a nonce, a 15-minute expiry and a unique constraint on use. The partner's download URL opens with the token in the URL fragment, and the token is also written to a local handoff file that the partner's SDK reads on first run — because a browser download followed by a manual install loses the fragment.
5. The receiving app claims
On first run the partner's SDK looks for the token, via the ghan:// protocol handler and the handoff file. It signs an install_claim with its own key and sends device signals alongside it: virtual-machine indicators, operating-system install age, a salted hardware hash that is never the raw value, and clock skew.
At this instant the advertiser's credits are charged and moved into escrow. No money has moved to anyone yet.
6. Forty-eight hours later, behaviour decides
The receiving SDK reports coarse usage counters — session starts and ends, feature counts, never content and never personal data. If the application is still present and has been used, the chain enters activated_48h, escrow releases, and the serving app earns.
If it has not, the hold refunds and the chain ends in rejected with a reason code the serving app can read through get_stats. Transparency applies to rejections too; a partner always learns why they were not paid.
Where the money sits at each moment
- Before the claim — the advertiser's credits are in their wallet. Nothing is reserved.
- **At
install_claim** —escrow_holdmoves the CPI out of the wallet into escrow. The ledger records it. - **At
activated_48h** —escrow_releaseplusearncredit the serving app with 70 percent of the CPI, or 84 percent of the value in credits. GHAN keeps 30 percent. - **At
rejected** — the hold reverses. The ledger records the reversal as a new line; nothing is ever edited.
The ledger table blocks UPDATE, DELETE and TRUNCATE with a database trigger. A correction in GHAN is always a new line, never a rewritten one. That is what makes get_ledger worth reading.
The three scoring layers
Before an app can trade at all it has to pass a vetting gate, and after it starts trading its behaviour replaces its reputation:
- Gate — pass or fail, automated, run on registration and again weekly. Notarisation or Authenticode, a clean malware scan, a domain at least six months old, a verified contact email, and a download URL that serves the bundle id it declared.
- Reputation — a 0-100 score built from AI visibility and sentiment, release cadence, reviews, and domain and social coherence. It is what GHAN knows about an app before it has traded anything.
- Behaviour — after 500 installs traded, this replaces reputation entirely. Retention of referred installs, uninstall rate, canary compliance, complaint rate.
What a partner's agent can verify without asking
get_ledgerreturns raw signed lines with event-chain references.get_statsreturns impressions, clicks, installs, cleared installs, retention and fraud rejections with reason codes.get_network_statsreturns the published network-wide numbers — average CPI by category, clearing rate, fraud percentage.get_scorereturns the score breakdown with machine-readable reasons for every gate failure.
Every milestone GHAN ships has the same acceptance rule: a partner's agent must be able to verify the claim from those outputs alone.
Questions people ask about this
How long does it take for an install to clear?
A standard install clears 48 hours after the claim, once the receiving SDK has confirmed the application is still present and has been used. Pairs of apps trading more than EUR 500 per day with each other clear on day-7 engagement instead, which is a slower and stricter bar applied exactly where the incentive to cheat is largest.
What happens if the referred user uninstalls within 48 hours?
Nothing clears and nobody is billed. The escrow hold placed at install_claim is released back to the advertiser automatically. The serving app earns nothing for that chain. This is the single most important design decision in GHAN - payout follows behaviour, never the install event.
Can a serving app fake installs to earn credits?
It would have to forge two independent ed25519 signatures, one of which belongs to an SDK running inside another company's signed binary, then survive a click-to-install-time histogram, a device check that reads the ASN of the claiming IP, and a cohort retention curve compared against the category baseline. The cost of faking a cleared install is designed to exceed the payout for it, which is the test every monetised feature in GHAN has to pass before it ships.
Does GHAN work if my app is offline most of the time?
Yes. Events are signed locally and queued, then delivered when connectivity returns. Token expiry is 15 minutes from issue, so a click made offline will not clear, but impressions, usage heartbeats and install claims all tolerate delayed delivery.
Machine-readable versions of this page: markdown · llms.txt · llms-full.txt · OpenAPI · AI catalog