TrustLens Linked-Account Detection: How It Works Without Storing Personal Data
Plugin Guide ยท TrustLens
Fraud Detection Without the Privacy Problem
A technical walkthrough of how TrustLens detects linked accounts using HMAC-SHA256 hashing โ what signals are compared, what reaches the database, and what does not.
The Concern Most Store Owners Actually Have
The question comes up every time someone looks seriously at fraud detection for their WooCommerce store: what data does this plugin actually collect, and am I going to end up holding personal information I shouldn’t have?
It is a reasonable question. GDPR makes data minimization a real obligation, not a suggestion. Collecting an IP address, a billing address, or a payment method fingerprint โ and then storing it in plain text in your database โ creates legal exposure and attracts attention you do not want if you ever have to respond to a data subject access request.
Linked-account detection is the part of fraud prevention that feels most invasive on the surface. You are essentially comparing customer fingerprints to find people who may be operating multiple accounts. The signals required to do that โ addresses, IPs, payment tokens โ are the same kinds of identifiers that appear in personal data regulations.
So the question worth asking is not “does TrustLens collect signals?” but “what form do those signals take once they reach the database?” The answer is technical and specific, and it matters for your compliance posture. This post walks through exactly what the code does.
This is a technical explainer, not legal advice
This post explains how TrustLens’s linked-account detection works mechanically. It does not constitute legal advice about GDPR compliance or data protection obligations. Your specific legal position depends on factors โ your jurisdiction, your privacy policy, your data processing agreements โ that are beyond the scope of a plugin documentation post. If GDPR compliance is a significant concern for your store, speak with a qualified legal professional.
What the Linked-Accounts Module Does
TrustLens’s linked-accounts module identifies customer accounts that appear to be operated by the same person. The most common case is multi-account fraud: a customer creates several accounts with different email addresses to claim first-order discounts multiple times, or to avoid a block placed on a previous account.
The module works by creating a fingerprint from each order โ a set of derived values from the order data โ and comparing those fingerprints across different customer accounts. When two accounts share a fingerprint, they are flagged as linked. The risk level of the linked accounts then factors into each customer’s trust score.
For a broader look at how this fits into the overall scoring system, see the guide to how TrustLens scores a WooCommerce customer โ it covers all eight detection modules and explains how signals combine into a final 0โ100 score.
The fingerprinting runs every time a new order is created, via the woocommerce_checkout_order_created hook. It does not run on-demand or in the background on data it has not seen before โ only on live order events and during historical sync, which processes your existing order history.
The Six Signals Used for Fingerprinting
TrustLens extracts up to six signal types from each order. These are the values used to build a customer’s fingerprint set. The source field for each is the corresponding WooCommerce order getter method โ not a third-party API call, not a browser cookie. Everything comes from the order data your store already holds.
| Signal type | Source in WooCommerce order | Preprocessing before hashing |
|---|---|---|
| Shipping address | address_1 + address_2 + city + postcode + country | Lowercased, punctuation stripped, common abbreviations expanded (“St” โ “Street”, “Ave” โ “Avenue” etc.) |
| Billing address | Same fields from billing side of order | Same normalization as shipping address |
| Phone number | get_billing_phone() |
Non-digit characters stripped; leading country code “1” removed for US/Canada numbers over 10 digits |
| IP address | get_customer_ip_address() |
No preprocessing; localhost addresses (127.0.0.1) are excluded entirely |
| Payment token | Stripe card fingerprint (_stripe_card_fingerprint), saved token ID (_payment_token_id), or card last-4 digits (_last4) |
Multiple tokens concatenated with “|” if more than one is available |
| Device user agent | get_customer_user_agent() |
No preprocessing; stored as-is |
A signal is only included if the value is non-empty. An order with no Stripe fingerprint and no saved payment token simply produces no payment-token fingerprint. The module works with whatever signals are present in the order data โ it does not fabricate missing values.
Each extracted signal is passed immediately to the hashing function. The raw value is used only briefly in memory during the fingerprint extraction step and is never written to a database column, a log file, or any other persistent storage.
How HMAC-SHA256 Hashing Works in Practice
Once a signal value has been extracted and preprocessed, TrustLens passes it through a single hashing function before any persistence occurs. That function is wstl_hash_personal_value(), which is defined in the plugin’s includes/functions.php. Here is the exact implementation:
function wstl_hash_personal_value( string $value, string $context ): string {
$value = trim( $value );
if ( '' === $value ) {
return '';
}
return hash_hmac( 'sha256', $context . '|' . $value, wp_salt( 'auth' ) );
}
Three things are happening here that are worth understanding individually.
The algorithm: HMAC-SHA256
SHA-256 alone is a one-way hash: you cannot reverse a SHA-256 hash to recover the original value without brute-forcing it. HMAC (Hash-based Message Authentication Code) adds a second layer: the hash is computed using a secret key. Without the key, knowing the hash output tells you nothing useful. You cannot verify a guess against the hash without access to the same key. Someone who reads your database cannot run a dictionary attack against an HMAC-SHA256 hash the way they might against a plain SHA-256 hash of a known-format value like a phone number.
The key: wp_salt('auth')
The keying material is your WordPress installation’s auth secret key โ the same key that WordPress uses for authentication cookies. This key is stored in your wp-config.php file and is unique to your site. It is generated at installation and differs on every WordPress site.
The consequence is important: a hash produced on your store cannot be compared to a hash produced on any other store, even for the same underlying value. If two different stores both hash the shipping address “123 Main Street, Springfield, IL” using this scheme, the resulting hashes will be different. The fingerprints are site-specific and non-portable by construction.
The context prefix
Before hashing, each value is prepended with a context string identifying the signal type: shipping_address|..., phone|..., ip_address|..., and so on. This prevents a hash collision across different signal types โ the hash of an IP address cannot accidentally match the hash of a phone number that happens to produce the same digits. Each fingerprint type lives in its own namespace within the hash space.
Why this matters for GDPR data minimization
GDPR’s data minimization principle asks whether you are storing more data than is necessary for your purpose. A keyed HMAC-SHA256 hash of a billing address serves the purpose of multi-account detection without storing the billing address itself. Whether that satisfies your specific GDPR obligations is a legal question, but the technical approach is designed to minimize what is held in persistent storage.
What Actually Reaches the Database
TrustLens stores fingerprint data in a custom table called wp_trustlens_fingerprints. The schema for a fingerprint row includes: the customer’s email hash (more on this below), the fingerprint type (e.g. “shipping_address”), the fingerprint hash itself (the HMAC-SHA256 output), an optional ISO country code for address types, and timestamps for when the fingerprint was first and last seen.
What is notably absent from every fingerprint row:
- The raw shipping address
- The raw billing address
- The phone number in any form
- The IP address
- The payment token or Stripe fingerprint
- The device user agent string
None of the original signal values appear anywhere in the database after the fingerprinting step completes. The only thing stored is a 64-character hexadecimal string (the HMAC-SHA256 output) alongside the label describing what type of signal it came from.
The comparison step โ finding linked accounts โ works by querying for other customers whose fingerprint hash matches on a given fingerprint type. Two accounts share a shipping address fingerprint if and only if both of them produced the same HMAC-SHA256 hash for the same (normalized) address. The query never touches the raw address; it only compares opaque hash values.
What TrustLens does store in plain form
The customer’s email address is stored in plain text in the wp_trustlens_customers table, alongside behavioral metrics like total orders, total refunds, and the current trust score. This is the same email address that already exists in your WooCommerce customer and order records. TrustLens holds it so that your admin interface can display customer profiles by name rather than by hash. This is standard WooCommerce data that your store holds already โ TrustLens does not introduce it as a new data point.
Data Lifecycle: Retention, Purging, and Key Rotation
Fingerprint data does not accumulate indefinitely. TrustLens runs a daily cleanup via WordPress’s scheduled events that purges fingerprints older than 365 days based on the last_seen timestamp. A fingerprint’s last_seen date updates each time an order is placed that produces a matching signal, so active customers who continue to order will naturally retain their fingerprints. Customers who stop ordering will have their fingerprints purged after a year of inactivity.
The 365-day window is a hardcoded default in the cleanup function. It is not currently configurable through the plugin’s settings interface.
What happens if you rotate your WordPress secret keys
This is the most important operational caveat about TrustLens’s hashing approach, and the plugin’s readme.txt calls it out explicitly:
TrustLens uses wp_salt('auth') as the keying material for all hashes. If you regenerate your WordPress secret keys โ whether via a security plugin’s “regenerate keys” feature or by editing wp-config.php directly โ every hash that TrustLens has stored becomes invalid. The plugin cannot match returning customers to their existing profiles, and linked-account detection resets entirely. The stored hashes were computed with the old key; they bear no relationship to hashes computed with the new key.
If you do rotate your WordPress secret keys, the plugin’s readme.txt recommends running the historical sync afterward to rebuild the customer table using the new keying material. Manually set blocks and allowlists on individual customer rows do not auto-recover from the sync โ those will need to be re-applied.
Key rotation and security trade-offs
Key rotation is a security best practice for some attack scenarios โ if your wp-config.php is compromised, rotating keys invalidates any active authentication sessions. But for TrustLens specifically, rotation has a cost: it wipes your accumulated fraud history. This is not unique to TrustLens โ any system that uses a site-specific secret for hashing faces this trade-off. Know before you rotate that you will be rebuilding your TrustLens profiles from scratch.
How Customer Email Addresses Are Handled
Customer email addresses play a dual role in TrustLens. They are stored in plain text in the customer table (as noted above), but they also serve as the primary key linking all of a customer’s fingerprints, events, and scoring signals together. That primary key is not the email address itself โ it is a keyed HMAC-SHA256 hash of the normalized email address.
The same wstl_hash_personal_value() function handles email hashing, with 'email' as the context prefix:
function wstl_get_email_hash( string $email ): string {
$normalized = wstl_normalize_email( $email );
return '' === $normalized ? '' : wstl_hash_personal_value( $normalized, 'email' );
}
The normalization step lowercases and trims the email address before hashing. This means [email protected] and [email protected] produce the same hash, which is necessary to reliably link guest and registered orders placed by the same customer.
Every fingerprint row in the database uses this email hash as its owner identifier, not the email address itself. When a query needs to find all fingerprints belonging to a customer, it looks up by hash. When a query needs to find all customers sharing a fingerprint, the result is a set of email hashes โ the admin interface then resolves those hashes back to email addresses for display purposes by joining against the customer table, which does hold the plain-text email.
This approach also handles guest checkout correctly. A guest order is identified by its billing email hash. If the same person later creates a registered account using the same email address, the hash matches and their full behavioral history โ including all fingerprints from their guest orders โ carries over to the registered account automatically. For more on how TrustLens handles the full customer profile, the post on reading a TrustLens customer profile walks through what each section of the profile page shows.
Does Any Data Leave Your Server?
By default, no. TrustLens operates entirely within your WordPress and WooCommerce installation. The fingerprinting, scoring, and storage all happen on your server. No customer data โ hashed or otherwise โ is sent to Webstepper or to any default third-party service.
There are three circumstances under which data does leave your server, all of them optional and explicitly configured:
- Freemius SDK activation opt-in. During plugin activation, Freemius (the licensing platform TrustLens uses) may offer to collect site metadata โ WordPress version, PHP version, plugin version, and optionally admin email. This collection requires your explicit opt-in. You can skip the opt-in entirely; the plugin operates in full with no data sent to Freemius at all beyond license checks. No customer data is involved in Freemius telemetry.
- Webhooks (Pro feature). If you configure webhooks in TrustLens Pro settings, the plugin sends HTTP POST requests to URL endpoints you specify. The payload includes the customer’s email hash (not the plain email address), their trust score, segment, and event details. The endpoint is entirely under your control โ you configure where the data goes. No webhooks fire by default; they require deliberate configuration.
- Chargeback tracking (Pro feature). If you configure Stripe or WooPayments integration for chargeback tracking, the plugin connects to those APIs using credentials you provide. This is an inbound data flow โ dispute data comes from Stripe or WooPayments into TrustLens โ not an outbound flow of your customer data to a third party.
If none of those three features are configured โ which is true for any standard free installation โ the plugin generates no external network traffic related to customer data.
GDPR Tools Built Into the Plugin
TrustLens integrates with WordPress’s standard privacy workflow, which appears in your WordPress admin under Tools โ Privacy. When a customer submits a data export or erasure request through the standard WordPress mechanism, TrustLens adds its data to the response.
For a data export request, TrustLens includes: the customer’s trust score and segment, their behavioral signal breakdown, any stored fingerprint hashes (labeled by type), category return statistics, and automation rule logs if applicable. The fingerprint hashes themselves are included in the export โ not the original signal values, because those are not stored. If a customer asks what data you hold about them in TrustLens, the export is the authoritative answer.
For a data erasure request, TrustLens deletes all of the above: the customer record, all events, all signals, all fingerprint hashes, category statistics, and any automation logs. The deletion is complete โ there is no partial erasure or anonymization step. After erasure, the customer is treated as a new customer on their next order.
Both integrations are available in the free version. They do not require any configuration beyond having WordPress’s privacy tools set up with a privacy page and a data handling email address.
For a look at how fraud detection interacts with the broader question of distinguishing policy abuse from genuine return disputes, the post on refund abuse versus chargeback fraud in WooCommerce covers where behavioral signals are most useful and where they reach their limits.
Shared Signals and False Positives
One practical consideration that affects both the utility and the accuracy of linked-account detection: some signals are legitimately shared by unrelated people.
A shared IP address is the most common example. A university campus, a large office building, or a household with multiple people ordering from the same router will all share an IP address. TrustLens does not treat a single shared signal as definitive evidence of a linked account. The customer profile view shows which signal types overlap between accounts, and the match strength โ the number of overlapping signal types โ is visible alongside the linked-account information.
One overlapping signal type (just a shared IP, or just a shared device user agent) is weaker evidence than four or five overlapping types (same address, same phone, same IP, same payment token). A household of two family members using the same WooCommerce store may share an IP address and a device fingerprint. A person running multiple accounts to farm your welcome discount will typically share a shipping address, a billing address, a phone number, and possibly a payment method as well.
The scoring system accounts for this proportionally: the penalty for linked accounts scales with the number of linked accounts and the risk level of those accounts. A weak link to one Normal-segment account produces a modest penalty. Multiple links to Critical-segment accounts produce a significant one.
Always check the match types before acting
Before treating a linked-account flag as evidence of abuse, look at which signal types overlap. A match on shared IP alone โ especially if that IP appears on many otherwise unrelated accounts โ is worth noting but not worth acting on. A match on shipping address plus phone number plus payment token across multiple accounts with no purchase history is a much stronger signal. The customer profile page shows all of this detail.
Key Takeaways
- TrustLens linked-account detection uses six signal types: shipping address, billing address, phone number, IP address, payment token, and device user agent โ all extracted from WooCommerce order data.
- Each signal value is preprocessed (normalized) and then passed through
hash_hmac('sha256', context . '|' . value, wp_salt('auth')). The raw value is never written to the database. - The HMAC key is your WordPress site’s
authsecret key, making all stored hashes site-specific and non-portable across different WordPress installations. - Customer email addresses are stored in plain text in the customer table (matching what WooCommerce already holds) but are used as a hash-based primary key internally for all fingerprint and event lookups.
- No customer data leaves your server by default. External connections only occur if you explicitly configure webhooks, Freemius opt-in during activation, or chargeback tracking integrations.
- Fingerprints are purged automatically after 365 days of inactivity via a daily cleanup cron.
- Rotating your WordPress secret keys invalidates all stored hashes and resets linked-account history. Run Historical Sync afterward to rebuild.
- GDPR data export and erasure are built in to the free version and respond to standard WordPress privacy workflow requests.
Frequently Asked Questions
Does TrustLens store IP addresses?
Not in plain text. When an IP address is included as a fingerprint signal, it is processed through hash_hmac('sha256', 'ip_address|' + ip, wp_salt('auth')) before storage. The resulting 64-character hexadecimal hash is what reaches the database. The original IP address is used only transiently in memory during the fingerprinting step and is not written anywhere persistently. Localhost addresses (127.0.0.1) are excluded entirely and produce no fingerprint.
Can the stored hashes be reversed to recover the original personal data?
In practice, no. HMAC-SHA256 is a one-way function, and the use of a site-specific secret key (your WordPress auth salt) as the HMAC key means that even a known-plaintext attack requires access to that key. Without the key, an attacker who gains read access to your database cannot determine what addresses or IP addresses were hashed. The hashes are also non-transferable: a hash computed on your site cannot be compared to a hash computed on any other WordPress site, even for the same underlying value.
Does TrustLens share customer data with Webstepper?
No. TrustLens operates entirely within your own WordPress installation. No customer data โ hashed or otherwise โ is sent to Webstepper by default. The only optional external connections are: the Freemius SDK during activation if you opt in (site metadata, no customer data), webhooks if you configure them in Pro (to endpoints you specify), and chargeback tracking if you connect a Stripe or WooPayments account in Pro (which pulls dispute data into your store, not the other way around).
Is TrustLens GDPR compliant?
TrustLens is designed to minimize stored personal data โ it hashes fingerprint signals rather than storing them in plain form, integrates with WordPress’s standard privacy export and erasure workflow, and keeps all processing local to your server by default. Whether its specific use in your store satisfies your GDPR obligations depends on factors including your privacy policy, your legal basis for processing, and your applicable jurisdiction. The plugin handles the technical side; the legal analysis is your responsibility or that of a qualified advisor.
What happens to a customer’s data when I delete them from TrustLens?
Deletion removes all of the following from TrustLens’s tables: the customer record (including plain-text email and trust score), all behavioral events, all scoring signals, all fingerprint hashes, category return statistics, and any automation rule logs. The deletion is complete and irreversible within TrustLens. Note that this does not affect the customer’s data in WooCommerce itself โ orders, addresses, and WooCommerce account details are managed by WooCommerce, not by TrustLens.
How long does TrustLens keep fingerprint data?
Fingerprints older than 365 days based on the last_seen timestamp are automatically purged by a daily scheduled cleanup. A fingerprint’s last-seen date updates whenever an order produces a matching signal, so active customers who continue to order will retain their fingerprints. Customers who stop ordering entirely will have their fingerprints purged after one year of inactivity. The 365-day retention period is hardcoded in the current version and is not configurable through the settings interface.
Why does rotating WordPress secret keys break TrustLens?
TrustLens uses wp_salt('auth') โ your WordPress auth secret key โ as the HMAC keying material for all stored hashes. When you rotate your WordPress secret keys, the new key produces different hash outputs for the same input values. All previously stored hashes were computed with the old key and are now meaningless: they cannot be matched against hashes computed with the new key. The result is that TrustLens can no longer recognize returning customers or find linked accounts until the historical sync is re-run to rebuild all hashes using the new key material.
Does TrustLens work with guest checkouts for linked-account detection?
Yes. Every customer โ guest or registered โ is identified internally by a keyed HMAC-SHA256 hash of their billing email address. Guest orders produce fingerprints for all available signals in the same way registered orders do. If a guest customer later registers with the same email address, their full fingerprint and behavioral history carries over automatically because the email hash matches. This matters for linked-account detection because a significant proportion of multi-account abuse involves guest checkouts specifically designed to avoid per-account history tracking.
See what TrustLens finds in your order history
Install TrustLens, run the historical sync, and find out what your customer risk picture actually looks like. The free version includes all eight detection modules and the complete scoring engine โ no trial limits.