# Birthday coupon email: PrestaShop module documentation

> Overview The module automatically sends your customers a personal discount code for three occasions: their birthday, the anniversary of their first valid order and the anniversary of their account creation.…

- Page: <https://www.datafirefly.com/en/documentation/dfkeydates/>
- Language: en
- Last updated: 2026-09-24
- Other languages: [fr](https://www.datafirefly.com/documentation/dfkeydates/index.md), [es](https://www.datafirefly.com/es/documentation/dfkeydates/index.md), [de](https://www.datafirefly.com/de/documentation/dfkeydates/index.md), [it](https://www.datafirefly.com/it/documentation/dfkeydates/index.md), [pl](https://www.datafirefly.com/pl/documentation/dfkeydates/index.md), [nl](https://www.datafirefly.com/nl/documentation/dfkeydates/index.md), [pt](https://www.datafirefly.com/pt/documentation/dfkeydates/index.md)
- Index: <https://www.datafirefly.com/en/documentation/llms.txt>

## Overview

The module automatically sends your customers a personal discount code for three occasions: their birthday, the anniversary of their first valid order and the anniversary of their account creation. Each code is a native PrestaShop cart rule, reserved for the customer and usable once. The module then measures the revenue of the orders placed with these codes.

Compatibility: PrestaShop 8.0 to 9.x, multistore, 8 languages (English, French, Spanish, German, Italian, Dutch, Polish, Portuguese).

## Installation

1. In **Modules > Module Manager**, click **Upload a module** and send the ZIP file.
2. The module creates two tables, registers its hooks, generates the scheduled task token and copies the email templates for each installed language.
3. A new **Birthdays and key dates** tab appears in the **Customers** menu. The module's **Configure** button also leads there.

To move from 1.0.0 to 1.1.0, simply upload the new ZIP: the upgrade script registers the new hooks.

The dashboard shows a "Getting started" checklist until the four key steps are done: enable a campaign, send yourself a test email, schedule the daily task and collect dates of birth.

## Setting up the campaigns

The **Campaigns** tab has one card per occasion. Turn it on with the switch at the top right: the settings and the email preview appear.

### The offer

- **Discount type**: percentage, fixed amount (in the default currency) or free shipping.
- **Value** and **Also offer free shipping** on top of a percentage or amount.
- **Minimum order (tax incl.)**: 0 for no minimum.
- **Validity after the date**: how many days the code stays valid after the date of the occasion.
- **Send in advance**: number of days before the date. 0 sends on the day itself.
- **Increase per extra year** and **Maximum value** (order and account anniversaries): for example 10% the first year, +2 per year, capped at 20%.
- **Exclude products already on sale** and **Can be combined with other vouchers**.

### Who receives it

- **Minimum number of valid orders**: 0 for the birthday includes customers who have never ordered.
- **Code prefix**: for example BDAY gives codes such as BDAY-7KQ2M9.
- **Customer groups**: none checked means all groups.

### The email

Edit the subject, headline and message for each language using the language tabs. The preview on the right updates live with the actual discount. Available tags: `{firstname}`, `{lastname}`, `{discount}`, `{code}`, `{expiry_date}`, `{min_amount}`, `{years}` (except birthday) and `{shop_name}`. An empty field uses the default text of the language.

The **Save and send a test** button sends the email to the logged-in employee's address, in their language.

## Scheduling the daily run

In **Automation and settings**, copy the scheduled task URL and call it once a day, ideally early in the morning. Example cron line:

```
0 7 * * * curl -s "https://your-store.com/module/dfkeydates/cron?token=YOUR_TOKEN" >/dev/null
```

Each run creates the codes of the day, sends the emails and reminders, links used codes to their order and deletes expired unused codes.

- **Catch-up for missed days** (2 by default): if the task did not run, the dates of the previous days are processed.
- **Maximum codes per run** (200 by default): the rest is sent at the next run.
- **Also run on shop visits**: without cron, the module runs on store visits, at most once an hour, after the page has been sent. It stops as soon as a real cron has been called within the last 26 hours.

The **Simulate today** (list of the codes that would go out, without sending anything), **Run now**, **Resync used codes** and **New token** buttons are on the same page.

Each customer receives at most one code per occasion and per year. You can therefore run the task several times without any risk of duplicates.

## Anti-abuse and date of birth collection

The **waiting period after sign-up or a birthday change** (30 days by default) blocks the birthday code for an account that is too recent or whose date has just been entered or changed in the store. Changes made by an employee in the back office do not trigger this period.

Dates of birth come from the native field of the customer account (**Customers > Settings > Birth date**). If this field is disabled, the module collects them itself:

- on the **order confirmation page**, when the date is unknown (option _Ask for the date of birth on the order confirmation page when it is unknown_);
- on the **My gifts and key dates** page of the customer account.

The dashboard shows the percentage of accounts with a known date.

## Reminder before expiry

Enable the reminder and choose how many days before expiry it goes out. It is only sent if the code has not been used. The reminder texts and the button text of all emails are set per language. The **Send a test reminder** button saves the settings and sends you an example.

## One-click code

The button in each email points to a signed link specific to the code. The module remembers the code and adds it to the cart as soon as the customer is logged in and the cart contains products. If the customer is not logged in, they are sent to the login page. If the minimum order is not reached, the code waits and applies as soon as it is. A code that has expired, has already been used or belongs to another customer is refused with a message.

## The "My gifts and key dates" customer page

Available from **My account**, it shows the active codes with a copy button and a **Use it in my cart** button, the customer's upcoming key dates, the date of birth form, previous gifts and a box to stop receiving these emails. You can hide this page in the settings.

## Statistics and revenue tracking

The **Dashboard** tab shows, for the selected period:

- the **revenue generated** excluding and including tax, calculated on valid orders that used a code, converted into the default currency;
- the **codes sent and used**, the conversion rate and the average basket;
- the **discount granted** and the return (revenue divided by discount);
- the **orders without the code** placed while a code was valid;
- a 12-month chart, performance by occasion, the sends of the next 30 days and the latest orders with a code.

Revenue is attributed to the period in which the code was sent. The **Codes sent** tab lists all codes with search, filters by occasion, status and date, email resend for an active code and CSV export. The back-office customer page also shows the codes sent to that customer.

## Cleanup of expired codes

The **Delete expired unused codes after** setting (30 days by default) deletes the matching cart rules to keep **Catalog > Discounts** readable. The module history and statistics are kept. Set 0 to never delete.

## GDPR

The module registers with PrestaShop's official GDPR module. Exporting a customer's data includes their codes and preferences, deletion erases the module history for that customer. Each customer can unsubscribe from these emails in their account.

## Multistore

Campaigns and settings are specific to each store. Select a store in the multistore menu to edit them. The codes created are restricted to the store concerned.

## FAQ and troubleshooting

### No code is sent

Check that at least one campaign is enabled, then use **Simulate today**. If the list is empty, no customer matches today's criteria: unknown date, anti-abuse waiting period, group not targeted, not enough orders or unsubscribed customer.

### Emails do not arrive

Send a test email from a campaign. If it does not arrive, check PrestaShop's email configuration in **Advanced Parameters > E-mail**. A code whose email failed is flagged in the code list and can be resent.

### An order is missing from the statistics

Only valid orders are counted. If an order was created in the back office by an employee without permission on the module, click **Resync used codes**; the daily task also does it automatically.
