Promo abuse is the use case where a single session verdict is not the right question. An attacker creating a hundred accounts on one device to claim a hundred trial credits looks like a human on every individual session — because they are. The signal is cross-session: one visitor fingerprint claiming the offer too many times, too fast.
The threat
Promotional abuse covers a family of scams that share one property: the offer is valuable enough per account to justify creating many accounts. Common shapes:- Free-trial farming. A new account gets 30 days of access, or $X of credit, or a hardware sample. Attackers spin up accounts until the offer dries up and resell credits or access.
- Referral bonus fraud. “Refer a friend, get $10.” Attackers self-refer by creating both sides of the transaction.
- Coupon / promo-code abuse. A one-per-customer code is tested, shared, or stacked. The same device redeems it twenty times under twenty identities.
- Signup-only bonuses. Platforms that hand out tokens, NFTs, credits, or airdrop allocations at account creation.
The flow
Run Tripwire normally at signup and/or claim
You need a session verdict for the fraud signal, and you need the durable visitor fingerprint.
Extract visitor_fingerprint.id from the verified token
This ID is stable across sessions on the same device.
Look up prior activity for that fingerprint
GET /v1/fingerprints/:visitorId returns lifecycle, session count, and recent verdict history.Check your own record of prior claims
Cross-reference the visitor ID against your own
promo_claims table.Client integration
The browser-side integration is the same as any other sensitive action — the difference is entirely on the server.waitForFingerprint() matters here. Promo abuse defense depends on getting a stable visitor_fingerprint.id, and that ID is only assigned once Tripwire has frozen the durable fingerprint server-side. Submitting before that can return a token without a visitor ID, which defeats the whole integration.
Server verification
Node.js
The cross-session check
isLikelyRepeatClaim is the piece that does the work. It combines two sources:
- Your
promo_claimstable. The ground truth for “this offer has already been given to this device.” Query it first — it’s cheap and decisive when positive. - Tripwire’s durable fingerprint record. Even if your own table says “no prior claim of this code,” the visitor fingerprint’s history can still flag the device as a serial claimer across other offers, or as part of a suspicious account constellation.
Node.js
/v1/fingerprints/:visitorId:
| Field | What it tells you |
|---|---|
lifecycle.first_seen_at | First time Tripwire saw this device anywhere on your site. |
lifecycle.last_seen_at | Most recent session on this device. |
lifecycle.seen_count | Total number of sessions Tripwire has frozen for this fingerprint. |
lifecycle.expires_at | When Tripwire will retire this fingerprint record. |
latest_request.ip_address | Most recent IP — useful for spotting residential proxy rotation. |
activity.sessions[] | Recent sessions with their decisions. Look for verdict: "bot" or many inconclusive in a short window. |
Scoring patterns
A singleisLikelyRepeatClaim → true is a strong block signal. You can go further by composing a few facts into a score:
- New fingerprint, many sessions in minutes. Classic “spin up ten browsers, claim ten promos” pattern.
- Seen many times, claim never before. A long-tenured device that hasn’t claimed this offer: probably fine.
- Seen many times, multiple claims across different offers. A device that keeps claiming offers under different accounts: very suspicious, even without a bot verdict.
lifecycle.expires_atin the past. The fingerprint record has aged out — treat as a new device.
When the visitor ID is missing
visitor_fingerprint is null on sessions where Tripwire couldn’t establish a durable ID — typically hardened privacy browsers (Firefox in resistFingerprinting mode, Brave with aggressive shields), very short sessions, or mobile webviews with storage disabled. Treat a missing visitor ID as “apply your normal one-per-account check, but don’t grant a generous promo” rather than as a block signal in itself. Most missing-ID sessions are real privacy-conscious users; some are intentional evasion. Don’t punish the first group to catch the second.
What’s next
Signup protection
Stop the account factory that feeds promo abuse.
Server verification
Reference for token verification and durable readback.
Fingerprints API
Full API shape for
GET /v1/fingerprints/:visitorId.Going to production
Rollout plan and monitoring.