Skip to main content
A loyalty program rewards genuine, repeated activity, so the payoff for faking it is steady: points, tier status, member pricing and referral credit. The fraud shape is a cluster of “different” members, each with its own login and email, that all trace back to one machine or one network, or a real member whose balance someone else drains after taking over the account. ShieldLabs links each member account to the devices and network behind it and detects Multi-accounting, Account sharing and Account takeover on your members directly. The Device ID ties the “different” members together, so you see how many of them share one device.

What is loyalty fraud?

Loyalty fraud is the gaming of a rewards or membership program (farming points, tiers or member perks) through multiple linked identities rather than real activity, or draining a real member’s points after taking over the account. One person runs several accounts to multiply signup bonuses, stack referral credit between their own profiles, or push a single identity into a higher reward tier than its genuine activity earns.

How ShieldLabs surfaces it

ShieldLabs ties each earning or redemption to the member account behind it, detects High-Risk Events on your members, and scores the action itself. Four layers answer four questions: The anchor for the device count is the Device ID, derived server-side, so a cookie clear, a private window or a rotated VPN IP does not reset it. The distinct accounts behind one Device ID are the members behind one machine. When a farmer rotates the public IP through a VPN, the Local IP, the address the browser itself reports, can expose the network behind the mask.

Prevent loyalty fraud

The rule to apply: on every earning and redemption action, read the member’s account (its worst band and linked devices), the action’s risk_score and named signals, and the device_id. Count the distinct accounts behind one device_id with the History API, and behind one local_ip.ip in your own webhook store, and when that count crosses your per-program limit, hold the perk for verification or deny it instead of paying the reward again. Weigh in the Risk Score (0-100) and the detection_flags: a masked action reusing one device is the farm tell, while a clean, single-account device earns and redeems with no friction. When a farm masks its public IP, compare public_ip.country with local_ip.country; detection_flags.ip_mismatch marks two different addresses and is informational (it does not change the Risk Score). ShieldLabs stops loyalty fraud by linking the accounts and scoring each action; you choose the action for each case. The steps below wire it up.

Build it

1

Identify on the action

Add the snippet to your signed-in pages and pass a hashed User HID with checkAuthenticatedUser on every one of them. Users, account-level risk and all four High-Risk Events are built on it. Within one visit (while a page of your site stays open in the browser, across route changes in a single-page app and across open tabs), checkAnonymous and checkAuthenticatedUser run at most one identification every five minutes for the same user. A call inside that window posts nothing, counts nothing, and its onInitialized handler receives { status: "not_initialized" }. On a multi-page site, a full page load in the only open tab can start a new visit with its own identification. So where points are earned or a perk is claimed, call forceCheckAuthenticatedUser when the user starts filling the form for that action (its first focus): it runs an identification every time, keeps the current Session ID and restarts the five-minute window, so the action always posts its own request ID. onInitialized fires when the check starts, before the snippet has sent the identification, so do not navigate away inside it: store the request ID and let the form submit normally. Pass the member’s hashed account id, never a raw email.
claim-reward.html
2

Read the scored result on the server

The scored result arrives by webhook with request_id, user_hid, device_id, visitor_id, risk_score, signals, detection_flags and observed_at. Cache it by request_id and read it back with the shared waitForScore helper, which falls back to a History API read by request_id. Because the durable device_id is the grouping key, you also read the account’s neighbours: how many distinct accounts that one device has already touched.
The accounts behind one device
3

Read the member behind the action

The redemption is one identification. The member behind it has a history, and for a loyalty program it is usually a long one. The shared accountView helper reads the member’s earlier identifications from the History API by user_hid: the worst band across them shows how risky the member has been, and its distinct Device IDs and public IPs are the devices and networks it is linked to. When a Multi-accounting, Account sharing or Account takeover event arrives for a member through the API or webhooks, or when you review it in the analytics dashboard, record it against the account in your own system with the event and its confidence, and the handler in the next step reads that record.In the analytics dashboard, the member’s card shows the same view: its band for the selected period, its High-Risk Events, each pill coloured by its confidence, and each linked device, visitor and IP with the band of the identifications it shares with the account. User, device, visitor and IP cards describes each part.
The Details section of the user card for User HID a91f3c7e5b2d4086 in the analytics dashboard with Linked devices open: 2 devices, one Trusted with 7 identifications and one Dangerous with 5, and the Linked local IPs counter showing 2.The Details section of the user card for User HID a91f3c7e5b2d4086 in the analytics dashboard in the dark theme with Linked devices open: 2 devices, one Trusted with 7 identifications and one Dangerous with 5, and the Linked local IPs counter showing 2.

The devices linked to one user in the analytics dashboard, with the band of the identifications they share.

4

Count the accounts behind the device and decide

The decision combines the member, the action’s risk signals and the account count behind the device. A masked action alone can be a real member on a corporate VPN; many accounts redeeming from one durable Device ID is the farm shape no single genuine member ever shows.
api/loyalty/redeem.js
5

See the spread over time

The per-action check catches a redemption right now. ShieldLabs also detects three High-Risk Events that matter for loyalty programs, each at Medium or High confidence, and they are available in the analytics dashboard, the API and webhooks:
Several member accounts run by one person, linked through the devices and network they share: the core farming shape. The confidence depends on the combination of evidence.
One member account used from several distinct devices: the tier or status-abuse shape, where one identity is pushed up by activity from many people.
An existing member account appearing in a new environment that points to someone else using it: the points-drain shape, where someone else redeems the member’s balance.
All three need the hashed User HID, which you pass with checkAuthenticatedUser on every signed-in page and with forceCheckAuthenticatedUser on the action. When one of these events arrives for a member, act on the account; you choose the action for each case. At the earning or redemption itself, the Risk Score and risk signals of the identification remain the input.On Overview, the Users and High-Risk Events panels count your members with each event at Medium and High confidence for the selected period, and each event tile opens Analytics with that event as a filter; switch to the Users tab to list the members who have it. Investigate a risky user walks through the review.
The Users and High-Risk Events panels of the analytics dashboard: 1,240 users split into 1,090 Trusted, 104 Risky users and 46 High-Risk Event users; Multi-accounting 22 users (14 Medium, 8 High confidence), Account sharing 12 (8 Medium, 4 High), Impossible travel 7 (5 Medium, 2 High) and Account takeover 5 (3 Medium, 2 High).The Users and High-Risk Events panels of the analytics dashboard in the dark theme: 1,240 users split into 1,090 Trusted, 104 Risky users and 46 High-Risk Event users; Multi-accounting 22 users (14 Medium, 8 High confidence), Account sharing 12 (8 Medium, 4 High), Impossible travel 7 (5 Medium, 2 High) and Account takeover 5 (3 Medium, 2 High).

Users and High-Risk Events on the Overview screen of the analytics dashboard, counted for the users active in the selected period.

History API reads never count against your included identifications. For high-volume earning flows, keep your own counters (members per Device ID and per local_ip.ip from the webhook) as the fast path, and reserve live History reads for the perks that are expensive to give away by mistake. The History API has no Local IP search, so the Local IP count always comes from your own store.
6

Tune to your program

Start in logging-only mode, watch how real members distribute, then set your limits and raise friction as conditions stack. A real member on a corporate VPN can reach the Suspicious band, so decide on the Risk Score plus the detection_flags plus the account count plus your own context, never the number alone.

Test it

You do not need a real farm to see this work. Redeem a perk once in your normal browser and note the device_id on the webhook. Then play the farmer: clear cookies or open a private window, and redeem again as a different member. The cookie_id and visitor_id change each time, but the same device_id returns, and the distinct-account count on that device climbs with each run. A second browser gets its own Device ID; the network the accounts share can still link them. Toggling a VPN lights up the risk signals and flips the matching detection_flags, all without changing the Device ID. Then search Analytics in the analytics dashboard for that Device ID and open it: Linked accounts lists every account you used in the test, each with the band of its identifications on that device. A guide, not a rule. Layer the conditions: a loyalty farm trips more than one, and friction should rise as they stack.

Next

Stop Multi-Accounting

Loyalty farming is a special case of one person running many accounts.

Account Takeover

Step up when a known member arrives on an unfamiliar device, before the points are drained.

Sybil Attack

When the linked identities exist to farm referral credit between each other.

High-Risk Events

Multi-accounting, Account sharing, Impossible travel and Account takeover, detected on your members.