Get in touch
  • OpenCart
  • Sales and conversion
  • v1.0.3

Double Opt-In Newsletter Subscription for OpenCart

Double opt-in plugin for OpenCart: subscription only activates after clicking a link in the email. Consent record with IP and date, one-click unsubscribe, CSV export. Free up to 200 subscribers, Pro unlimited.

Pro 1 290 UAH lifetime
Download Free
Compatibility
OpenCart 4.0.2 – 4.1.x
PHP
7.4 or newer
Licence
one site, lifetime
Trial
7 days, no card, one per site
Updated
26.09.2026
Or all 173 Pro modules with All Access — 4 990 ₴ / year

What Free has,
and what Pro adds

The free version works with no time limit. Pro adds the rest of the features in the table.

Feature Free Pro
Subscription only activates after clicking a link from the person's own inbox ✔ ✔
Consent record: source, IP, user agent, request time and confirmation time ✔ ✔
Subordinates OpenCart's stock tick box at registration and in the account area ✔ ✔
One-click unsubscribe from any email ✔ ✔
Four emails: confirmation, welcome, reminder, farewell ✔ ✔
Subscriber grid with filters by status, source and period ✔ ✔
CSV export with proof of consent, UTF-8 with BOM ✔ ✔
Honeypot, signed timestamp and per-IP request limit ✔ ✔
Auto-deletes unconfirmed requests after N days ✔ ✔
One-off import of existing subscribers — by button, not on install ✔ ✔
Per-language email text editing — ✔
One scheduled reminder for the unconfirmed — ✔

What it looks like

The page shown after clicking the link in the email. It's rendered with the store's own template, so it inherits the look of your theme.
The page shown after clicking the link in the email. It’s rendered with the store’s own template, so it inherits the look of your theme.
Subscriber grid: status, source (form / account), IP, request date and confirmation date — the same proof of consent that goes into the CSV.
Subscriber grid: status, source (form / account), IP, request date and confirmation date — the same proof of consent that goes into the CSV.
Module settings in the OpenCart 4.1 admin: the stock newsletter tick box is now subordinate to confirmation, plus link expiry and a form snippet for the theme.
Module settings in the OpenCart 4.1 admin: the stock newsletter tick box is now subordinate to confirmation, plus link expiry and a form snippet for the theme.

The trial starts when you ask

A fresh install is the free version, nothing switches on by itself. The “Try Pro for 7 days” button → e-mail → the key right in the window and by e-mail.

One key — one site

Moving the store? Unbind the licence on the old domain and activate it on the new one yourself.

Technical requirements

  • OpenCart 4.0.2 – 4.1.x (3.x and 2.3 versions are in development).
  • PHP 7.4+ (also runs on 8.0–8.3).
  • MySQL/MariaDB with InnoDB and utf8mb4 support.
  • Store mail configured (System → Settings → Mail): the module sends emails through the same transport as the rest of the store — no separate credentials needed.

Version history

v1.0.3 Current 26.09.2026

The subscriber list with a filter opens again on the PDO database driver.

v1.0.2

The “confirm subscription” and “unsubscribe” links no longer fire for an e-mail scanner.

v1.0.1

A purchased OpenCart licence works with no time limit.

All versions (4)
v1.0.0 First release

Full double opt-in cycle, subordinating the stock tick box, four emails editable per language, subscriber grid with proof of consent, CSV export, scheduled reminders and retention, one-off…

Frequently bought with Double Opt-In Newsletter Subscription for OpenCart

4 modules in one order — 40% cheaper than separately

“Store starter” bundle Double Opt-In Newsletter Subscription Nova Poshta Premium LiqPay Telegram notifications and Viber/SMS for customers Need more — all 173 modules in All Access for 4 990 ₴.
3 790 ₴ lifetime instead of 6 260 UAH bought separately
Buy the bundle →

Full module description

Stock OpenCart treats the tick box itself as consent. A customer ticks “Subscribe to newsletter” during registration, and customer.newsletter = 1 appears in the database immediately. No confirmation, no date, no trace of where that consent came from. An address someone typed into a stranger’s registration form can’t be removed from the list, and there’s nothing to prove the person actually agreed.

This module turns that tick box into a request. The flag only goes up after the person clicks a link from their own inbox — and that’s when a consent record appears in the database, complete with a timestamp, source, and IP.

What the buyer sees

In the footer (or wherever you place the form) — an email field, optionally a name field, and a button. After submitting, the person immediately sees: “Almost done — check your inbox and follow the link in the email. We won’t send you anything until then.”

The email itself has one action — a confirmation link. Clicking it opens a store page in your theme (using the standard common/success template, so the look inherits from the theme) reading “Subscription confirmed”. A short welcome email follows, already containing a one-click unsubscribe link.

If someone enters an address that’s already confirmed, they see “This address is already subscribed” — and get no further email. That’s deliberate: otherwise anyone could flood a stranger’s inbox with “confirmations” just by typing their address into the form.

What the admin gets

A dedicated subscriber grid in the module settings: address, name, status (pending / confirmed / unsubscribed / error), source (form, account, admin, import), language, IP, request date, and confirmation date. Filters by status, source, address, and period.

A “Resend” button for anyone who hasn’t confirmed. CSV export of all confirmed addresses — together with proof of consent (source, IP, both dates), in UTF-8 with BOM, so Excel doesn’t mangle names into garbled characters.

Per-status counters are always visible, so you see the real size of the list, not “how many people once ticked a box”.

How it works, step by step

  1. Someone leaves an address — in the module’s own form or via the stock tick box at registration or in the account area.
  2. A row is created in a dedicated table with status “pending”, a token, IP, user agent, language, and source. If the tick box was used at registration, the module pushes customer.newsletter back to 0 — until there’s consent, there’s none in the database either.
  3. A confirmation email goes out in the language of the storefront version the request came from.
  4. Clicking the link moves the row to “confirmed”, records the date, and raises the stock customer.newsletter flag, so the rest of the store sees the same picture.
  5. After a configured number of hours, anyone who hasn’t confirmed gets exactly one reminder. The row is marked “reminded” regardless of whether the email actually arrived, so a dead address doesn’t loop forever.
  6. Unconfirmed requests older than N days are deleted automatically. An address that never confirmed isn’t a subscriber, and there’s no reason to keep it indefinitely.

Unsubscribing works in one click from any email: following the link moves the row to “unsubscribed”, lowers the stock flag, and (optionally) sends a short confirmation, so the person keeps written proof.

Under the hood

A single dedicated table, cc_news_subscriber: one row per (store, address) pair, with status, token, and proof of consent. A unique key on the pair prevents duplicates, and a repeat request from the same address revives that same row with a new token — so the link from an old email stops working.

The token is 48 hexadecimal characters from random_bytes. The same token serves both confirmation and unsubscribing: once confirmed, it deliberately doesn’t change, because it’s exactly what the “unsubscribe” link in every future email relies on.

Form protection is a hidden honeypot, out of the document flow and off the tab order, plus a signed timestamp (an HMAC over the installation’s own parameters) that can’t be rewritten client-side. The stamp is valid for 24 hours, so the form survives full page caching. On top of that, there’s a per-IP hourly request limit and, optionally, the store’s own captcha.

Email texts live in a library rather than language files: an email is built from three different contexts (storefront, admin, scheduled run), and the email’s language is the subscriber’s language, not the language of the current request. An empty template field always falls back to the built-in text, and an unknown language falls back to English.

The module doesn’t touch a single core file: it works through OpenCart’s standard events and its own storefront routes.

Installation

  1. Extensions → Installer → upload the zip.
  2. Extensions → Modules → find “Double Opt-In Subscription” → click “+”. This step creates the table and registers the events and scheduled task.
  3. Open the settings, enable the module, and save.
  4. Insert the form wherever needed in the theme: {{ cc_newsletter }} in any Twig template.
  5. If the store already has subscribers via the stock tick box, click “Import existing subscribers”. Import runs once, manually only: it enrols them as confirmed, because the store already considers them subscribers, and it never brings back anyone who unsubscribed.

Questions
about the module

Didn't find the answer? Message us on Telegram and we'll reply within a business day.

@catcode_support Setup, compatibility, activation
Will this break my registration?

No. The event handler is wrapped so that any error inside it never reaches the customer.

What if I don't want the module touching the stock tick box?

There's a "Don't touch" switch in settings — then only the module's own form is active.

What happens to existing subscribers?

Nothing, until you press the import button yourself. The module imports no one on installation.

How long does the confirmation link last?

72 hours by default, configurable.

Is data deleted when the module is removed?

No. The subscriber table is deliberately kept — it's proof of consent for every address.

Not quite what you are looking for?

We build custom modules for WordPress, WooCommerce, OpenCart and Shopify. Tell us about the task and we'll prepare an estimate.

Order a custom module