What is Coupon & Promo Abuse?
Coupon and promo abuse occurs when individuals exploit a business's promotional offers for unauthorized discounts or advantages, leading to potential financial losses. Tactics typically include redeeming the same promotional code multiple times, coupon glittering, stacking codes in unintended ways, creating multiple accounts to benefit from one-time offers, or using bots to seize high-value promotional items.
Why is Coupon & Promo Abuse Prevention Important?
While increased sales benefit your business, coupon and promo abuse can lead to financial losses from unwarranted discounts and deplete inventory intended for genuine customers. Preventing customers, either signed-in or anonymous, from abusing your coupons and promotions can help:
Prevent Financial Losses
Preventing coupon and promo abuse is essential to avoid financial losses from unauthorized discounts or fraudulent transactions. When these offers are exploited, they can negatively impact profits and potentially jeopardize the financial health of the business.
Increase Sales
By curbing abuse, companies can direct promotions to their intended audience: genuine customers planning to purchase. This active approach enhances the effectiveness of sales campaigns and, subsequently, increases overall sales by concentrating resources on users who are most likely to buy products.
Boost Legitimate Customer Experience
Preventing abuse ensures promotions and inventory remain accessible to real customers as intended. If abuse goes unchecked, it could lead to key items selling out or special offers becoming unavailable, creating a poor experience for legitimate customers.
Improve Marketing Analytics Accuracy
Controlling coupon and promo abuse significantly improves the accuracy of marketing data, making it easier to extract meaningful insights. This reliable data on promotional engagement, customer behavior, and ROI assists companies in making better decisions and strategic plans.
How to Increase Revenue Through Coupon Abuse Prevention
Install a Browser Identification Service
Device identification services like Fingerprint Pro can accurately identify anonymous visitor traffic by uniquely identifying their browsers. With JavaScript that runs in the background, Fingerprint Pro generates a unique identifier anytime someone performs a critical action, such as checking out. Additionally, we leverage server-side tools to validate incoming fingerprints, adhering to the best practice of never trusting data from the client side. With our visitor identification API, you can protect your storefront’s coupon system against fraudsters without harming the checkout experience for friendly customers.
Configuring Fingerprint Pro for Coupon Abuse Prevention
Here's a basic logic for safeguarding coupon codes, but your business needs might necessitate additional checks.
First, you must incorporate the Fingerprint Pro JavaScript agent into your store's front end to collect browser signals and generate a unique identifier. If your front end is built on a framework like Next.js or Vue, you can streamline the process using one of our open-source libraries.
// Initialize the agent.
const fpPromise = import("https://fpjscdn.net/v3/<your-public-api-key>").then(
(FingerprintJS) =>
FingerprintJS.load({
endpoint: "https://metrics.yourdomain.com",
})
);
For production deployments, we recommend routing requests to Fingerprint's APIs through your domain using the endpoint
parameter. This prevents ad blockers from disrupting identification requests and improves accuracy. We offer a variety of ways to do this, which you can learn more about in our guide on how to protect your JavaScript agent from ad blockers.
When a customer attempts to use a coupon, make an identification request and send the requestId
with the coupon code.
async function onCheckout() {
// Collect browser signals and request visitor identification
// from the Fingerprint API. The response contains a `requestId`.
const { requestId } = await (await fpPromise).get();
const couponData = {
couponCode,
requestId,
};
const response = await fetch(`/api/checkout/coupons`, {
method: "POST",
body: JSON.stringify(couponData),
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
}
The following steps should be performed on the backend using data provided by the Fingerprint Pro Server API. If your backend logic is built on top of Node.js or any other popular server-side framework or language, you can use one of our Fingerprint Server API SDKs. Alternatively, one can also use the Webhooks functionality.
Let's check that the requestId
is legitimate by hitting the Server API /events
endpoint.
const requestId = req.body.requestId;
const couponCode = req.body.couponCode;
const fingerprintServerApiUrl = new URL(
`https://api.fpjs.io/events/${requestId}`
);
const requestOptions = {
method: "GET",
headers: {
"Auth-API-Key": "<secret-api-key>",
},
};
const fingerprintServerApiResponse = await fetch(
fingerprintServerApiUrl.href,
requestOptions
);
// If there's something wrong with the provided data,
// the Server API will return a non-2xx response.
// We consider these data unreliable.
if (
fingerprintServerApiResponse.status < 200 ||
fingerprintServerApiResponse.status > 299
) {
// Handle the error internally and do not allow
// the coupon code to be applied.
reportSuspiciousActivity(req);
return getForbiddenResponse();
}
const requestData = await fingerprintServerApiResponse.json();
const visitorData = requestData?.products?.identification?.data;
The Server API response must contain information about this specific identification request. If not, the request might have been tampered with and we don't trust this identification attempt.
// The returned data must have the expected properties.
if (requestData.error || visitorData?.visitorId == undefined) {
reportSuspiciousActivity(req);
return getForbiddenResponse();
}
An attacker might have acquired a valid request ID via phishing. It's recommended to check the freshness of the identification request to prevent replay attacks.
// Fingerprinting event must be a maximum of 3 seconds old.
if (new Date().getTime() - visitorData.timestamp > 3000) {
return getForbiddenResponse();
}
To ensure the identification event came from the same IP as the coupon request, compare the IP addresses from each request for a match.
// This is an example of obtaining the client's IP address.
// In most cases, it's a good idea to look for the right-most
// external IP address in the list to prevent spoofing.
if (request.headers["x-forwarded-for"].split(",")[0] !== visitorData.ip) {
return getForbiddenResponse();
}
The Fingerprint API request should always originate from a trusted production website. Check the origin in the response to ensure it is coming from your website.
const ourOrigins = ["https://yourdomain.com"];
const visitorDataOrigin = new URL(visitorData.url).origin;
// Confirm that the request is from a known origin.
if (
visitorDataOrigin !== request.headers["origin"] ||
!ourOrigins.includes(visitorDataOrigin) ||
!ourOrigins.includes(request.headers["origin"])
) {
return getForbiddenResponse();
}
During the checkout process, such as when a button like "Apply Coupon" is clicked, verify if the coupon exists and apply your established coupon policies and rules. In the example below, we check if the coupon had been already claimed by the visitor before.
// Check if a coupon exists with the given coupon code.
export async function checkCoupon(code) {
return await CouponCode.findOne({
where: {
code: {
[Op.eq]: code,
},
},
});
}
// Check if the `visitorId` has used the coupon code already.
async function getVisitorClaim(visitorId, code) {
return await CouponClaim.findOne({
where: { visitorId, code },
});
}
const coupon = await checkCoupon(couponCode);
// Return an error if the coupon doesn't exist.
if (!coupon) {
return getForbiddenResponse(
res,
"Provided coupon code does not exist.",
"error"
);
}
const wasCouponClaimedByVisitor = await getVisitorClaim(
visitorData.visitorId,
couponCode
);
// Return an error if the visitor has already claimed the coupon.
if (wasCouponClaimedByVisitor) {
return getForbiddenResponse(
res,
"You have already used this coupon.",
"error"
);
}
You can also check if the visitor claimed another coupon recently. If everything is fine, we mark the coupon as claimed in the database and adjust the price accordingly.
async function checkVisitorClaimedRecently(visitorId) {
const oneHourBefore = new Date();
oneHourBefore.setHours(oneHourBefore.getHours() - 1);
return await CouponClaim.findOne({
where: {
visitorId,
timestamp: {
[Op.between]: [oneHourBefore, new Date()],
},
},
});
}
// Claim the coupon on behalf of the visitor.
export async function claimCoupon(visitorId, code) {
const claim = await CouponClaim.create({
code,
visitorId,
timestamp: new Date(),
});
await claim.save();
return claim;
}
const visitorClaimedAnotherCouponRecently = await checkVisitorClaimedRecently(
visitorData.visitorId
);
if (visitorClaimedAnotherCouponRecently) {
return getForbiddenResponse(
res,
"The visitor claimed another coupon recently.",
"error"
);
}
await claimCoupon(visitorData.visitorId, couponCode);
return getOkResponse(
res,
`Coupon claimed successfully, you get a discount!`,
"success"
);
Explore Our Coupon Abuse Prevention Demo
We built a fully open-source coupon abuse prevention demo to demonstrate the concepts above. Use this demo to see how you can use Fingerprint Pro and simple logic rules to prevent coupon and promo abuse. Feel free to view the live demo on CodeSandbox or jump into the GitHub repo for code. If you have any questions or want to learn more about coupon and promo abuse prevention, please contact our support team.
FAQ
Coupon and promo abuse occurs when customers exploit discounts in ways not intended by the business, leading to revenue loss and unfair advantages.
By analyzing unusual patterns in coupon usage, such as repeated use of a coupon from the same device or excessive account creation from the same device.
Leveraging fingerprinting to identify devices and limiting promotions to one per device. Additionally, businesses can use unique codes, implement time restrictions, and employ other factors of verification to help mitigate abuse.