=== PopMint ===
Contributors: denm
Tags: popup, email, newsletter, subscribe, optin
Requires at least: 6.4
Tested up to: 7.0
Requires PHP: 8.0
Stable tag: 1.1.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Email capture popup with timing, exit intent and scroll triggers, an optional always-available side tab, spam protection and built-in analytics.

== Description ==

PopMint collects email addresses with a popup that respects your visitors. It works out of the box: install it, write your offer, and addresses are stored in your site with a CSV export. Connect a mailing service later if you need one.

**Two ways to show the popup**

* Automatic triggers: after a delay, on exit intent, or at a scroll depth.
* A side tab pinned to the edge of the screen. The visitor opens the popup when they want it, and you can switch automatic opening off completely.

The side tab sits left, right, top or bottom, carries your own text, and can be moved along that edge so it never collides with a support chat widget.

**Where subscribers go**

* This site, with a CSV export. No account anywhere, works immediately.
* Mailchimp.
* MailerLite.
* Sendy, your own self-hosted installation.
* A webhook, for Zapier, Make or your own endpoint. Requests can be signed so the receiver can verify them.

You can also keep a local copy while using an external service, so a broken integration never silently loses signups.

**Spam protection without a third party**

* Hidden honeypot fields that only scripts fill in.
* A generous cap on how many signups one visitor can send in a row.
* Rejections answer slowly and never say which check stopped them, so a script cannot learn how to pass next time.

Nothing is sent to an external anti-spam service, there is no captcha, and no visitor data leaves your site unless you configure a mailing provider yourself. Checking whether an address is real is left to your mailing service, which does it better anyway.

**Analytics that respect privacy**

Views, submissions, subscribers and conversion rate, broken down by trigger, plus a dashboard summary. The analytics table stores a one-way hash of each address, never the address itself.

**Built for any site**

Neutral default copy that suits a shop, a blog and a service business alike, no branding, light and dark themes, color controls, width, corner radius and title size, optional logo, path and device targeting, and a token-protected preview link for checking the popup on a live site without showing it to visitors.

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/`, or install it from the Plugins screen.
2. Activate it.
3. Open **PopMint** in the admin menu, write your offer on the Popup tab, and choose how it opens on the Display tab.

Subscribers are stored in your site until you pick a different provider on the Subscribers tab.

== Frequently Asked Questions ==

= Can I stop the popup from opening on its own? =

Yes. Set the display mode to "Side tab only" on the Display tab. The popup then opens only when a visitor clicks the tab.

= Does the side tab respect the frequency settings? =

No, on purpose. The visitor asked for it, so the tab always works even if the popup was closed earlier.

= Do I need a mailing service? =

No. The default provider stores addresses in your own database and exports them as CSV.

= Which mailing services are supported? =

Mailchimp, MailerLite and Sendy are built in. Anything else is covered by the webhook, which posts each signup as JSON and works with Zapier, Make or your own endpoint. You can also keep collecting addresses in your own site and import the CSV into any service later.

= Can I open the popup from my own button or menu link? =

Yes. Add the class `popmint-open` to any element, and clicking it opens the popup. It works on links, buttons and anything else, and it ignores the frequency rules because the visitor asked for it.

= What does the plugin store about my visitors? =

The subscriber table holds the address and, if you asked for it, the first name. The analytics table holds no personal data at all: only what happened, when, and which trigger produced it. Frequency capping uses the visitor's own browser storage, not a profile on the server. PopMint takes part in the WordPress privacy tools, so a data export or erase request covers its data too.

= Does the plugin send data anywhere? =

Only to the provider you configure yourself: your Sendy installation, MailerLite, or your webhook URL. With the default local provider no external request is made at all.

= Can I link my privacy policy from the popup? =

It is added for you. If the site has a privacy policy page set in Settings, a link to it appears next to the consent line.

= Is the popup accessible? =

It is a real dialog: focus moves into it, stays inside while it is open, returns to where it came from on close, and Escape closes it. The side tab is a real button, not a styled link.

= I activated the plugin and the popup is not there =

Clear your cache. If the site runs a caching plugin or sits behind a host CDN, visitors are still being served the copy of the page that was stored before you activated PopMint, and some hosts keep pages for a week. Clearing the cache once after activation is all it takes.

= Does it work with page caching? =

Yes. Every decision about whether to open the popup is made in the browser, so a cached page behaves the same as a fresh one. The security token inside the form is refreshed automatically when a cached page outlives it, so signups keep working even on pages that have sat in the cache for days.

= Will it hurt Core Web Vitals? =

The popup is fixed-position and rendered in the footer, so it does not shift layout. Assets load only on pages where the popup can actually appear.

== External services ==

PopMint contacts an external service only when you configure one as your subscription provider. With the default provider ("Store in this site") no external request is made.

**Sendy** (self-hosted, address you provide)
Used to add a subscriber to your list. Sends: email address, first name if collected, list ID, API key, the trigger that produced the signup, and your site URL as referrer. Sent at the moment a visitor subscribes. Sendy is software you host yourself, so its terms and privacy policy are your own.

**Mailchimp** (https://mailchimp.com)
Used to add a subscriber to your audience. Sends: email address, first name if collected, and a tag naming the trigger that produced the signup. Sent at the moment a visitor subscribes. The request goes to the data center encoded in your own API key, for example us14.api.mailchimp.com.
Terms: https://mailchimp.com/legal/terms/
Privacy policy: https://www.intuit.com/privacy/statement/

**MailerLite** (https://www.mailerlite.com)
Used to add a subscriber to your account. Sends: email address, first name if collected, the trigger name, and the group ID you configure. Sent at the moment a visitor subscribes.
Terms: https://www.mailerlite.com/legal/terms-of-service
Privacy policy: https://www.mailerlite.com/legal/privacy-policy

**Webhook** (any URL you provide)
Used to forward a signup to a service of your choice. Sends: email address, first name if collected, the trigger name, your site URL and a timestamp. Sent at the moment a visitor subscribes. The terms and privacy policy are those of whichever service you point it at.

== Screenshots ==

1. The side tab sits quietly on the edge of the page. The popup opens only when someone clicks it.
2. The popup itself, with the text it ships with.
3. Popup settings, with the live preview beside them.
4. Display settings: how the popup opens, the side tab, how often a visitor sees it and where.
5. Subscriber providers, spam limits and the stored list with CSV export.

== Changelog ==

= 1.1.0 =
* Mailchimp added as a subscription provider.
* The provider banner says how many signups were refused and stored nowhere in the last 30 days.
* Appearance is set with controls instead of free-form CSS: corner radius and title size joined the existing width and color settings, and the Custom CSS box is gone.
* Rate limit counters are kept in one record of a bounded size, so a flood of requests can no longer grow the options table.

= 1.0.0 =
* First release.

== Upgrade Notice ==

= 1.1.0 =
The Custom CSS box has been replaced by corner radius and title size controls.

= 1.0.0 =
First release.
