{"id":305905,"date":"2026-05-11T08:59:01","date_gmt":"2026-05-11T08:59:01","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/flexa-unsubscribe\/"},"modified":"2026-05-11T09:03:22","modified_gmt":"2026-05-11T09:03:22","slug":"flexa-unsubscribe","status":"publish","type":"plugin","link":"https:\/\/fa.wordpress.org\/plugins\/flexa-unsubscribe\/","author":23412324,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"3.0.2","stable_tag":"3.0.2","tested":"6.9.4","requires":"5.8","requires_php":"7.4","requires_plugins":null,"header_name":"Flexa Unsubscribe","header_author":"flexatech","header_description":"Professional email unsubscribe management with HMAC tokens, auto-append logic, and CSV export.","assets_banners_color":"faf8ff","last_updated":"2026-05-11 09:03:22","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":30,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"3.0.2":{"tag":"3.0.2","author":"flexatech","date":"2026-05-11 09:03:22"}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon.svg":{"filename":"icon.svg","revision":3528475,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3528443,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["3.0.2"],"block_files":[],"assets_screenshots":[],"screenshots":[],"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[267,131785,5825,44115,9755],"plugin_category":[41],"plugin_contributors":[255540],"plugin_business_model":[],"class_list":["post-305905","plugin","type-plugin","status-publish","hentry","plugin_tags-email","plugin_tags-gdpr","plugin_tags-mailing-list","plugin_tags-opt-out","plugin_tags-unsubscribe","plugin_category-communication","plugin_contributors-flexatech","plugin_committers-flexatech"],"banners":[],"icons":{"svg":"https:\/\/ps.w.org\/flexa-unsubscribe\/assets\/icon.svg?rev=3528475","icon":"https:\/\/ps.w.org\/flexa-unsubscribe\/assets\/icon.svg?rev=3528475","icon_2x":false,"generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p><strong>Flexa Unsubscribe<\/strong> adds a complete unsubscribe workflow to every email WordPress sends, with a fully-branded admin UI for managing opt-outs, analytics, and the public unsubscribe page.<\/p>\n\n<ul>\n<li><strong>Auto-appends a secure unsubscribe button<\/strong> to outgoing single-recipient emails. Tokens are HMAC-signed using the <code>AUTH_KEY<\/code> in <code>wp-config.php<\/code>, so no database lookup is needed to verify a link.<\/li>\n<li><strong>Blocks outbound mail to unsubscribed addresses<\/strong> before it reaches the mail server. Blocked attempts are logged to a dedicated audit table.<\/li>\n<li><strong>Honours an exclude-keywords list<\/strong> (default: <code>Order, Password, Invoice<\/code>) so transactional mail never gets an unsubscribe link and never gets blocked.<\/li>\n<li><strong>Re-subscribe URL<\/strong> is supported as a first-class action \u2014 the plugin can tell opt-outs from opt-backs.<\/li>\n<li><strong>Customisable public page<\/strong> \u2014 every color, font, and string on the unsubscribe\/re-subscribe templates is editable from the admin with a live preview.<\/li>\n<\/ul>\n\n<h3>Admin UI<\/h3>\n\n<p>Starting with v3.0.0 the admin is a React single-page application with seven screens:<\/p>\n\n<ul>\n<li><strong>Dashboard<\/strong> \u2014 stats cards + bar chart of unsubscribes over time + pie chart of top reasons.<\/li>\n<li><strong>Unsubscribes \/ Blocked emails \/ Re-subscribed<\/strong> \u2014 paginated tables with sorting, per-row delete, and CSV export.<\/li>\n<li><strong>Reasons<\/strong> \u2014 manage the dropdown options shown on the public unsubscribe form; click-to-edit, \u2191\/\u2193 reorder.<\/li>\n<li><strong>Settings<\/strong> \u2014 enable\/disable auto-append + blocking, tune the exclude-keywords list.<\/li>\n<li><strong>Appearance<\/strong> \u2014 19 tokens (colors, typography, copy) across three tabs with a live preview panel.<\/li>\n<\/ul>\n\n<p>All screens are powered by a REST API under <code>\/wp-json\/flexa-unsubscribe\/v1\/<\/code>, so external integrations can plug in too.<\/p>\n\n<p><strong>Source code for compiled JavaScript and CSS<\/strong><\/p>\n\n<p>The plugin ships with minified\/compiled JavaScript and CSS in <code>assets\/dist\/<\/code>. The human-readable source code for these assets is <strong>publicly available<\/strong> and maintained at:<\/p>\n\n<p>https:\/\/github.com\/flexatech\/flexa-unsubscribe<\/p>\n\n<p>Source lives in the <code>apps\/admin<\/code> (admin UI) and <code>apps\/frontend<\/code> (product page UI) directories. Build tools used: <strong>pnpm<\/strong>, <strong>Vite<\/strong>, <strong>React<\/strong>, <strong>TypeScript<\/strong>. To build from source: clone the repository, run <code>pnpm install<\/code> from the plugin root, then build the admin and frontend apps (see the repository README for exact commands). This allows the code to be reviewed, studied, and forked.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin files to <code>\/wp-content\/plugins\/flexa-unsubscribe<\/code>, or install through the WordPress <strong>Plugins<\/strong> screen.<\/li>\n<li>Activate the plugin through the <strong>Plugins<\/strong> screen.<\/li>\n<li>On activation the plugin provisions three database tables: <code>{prefix}flexa_unsubscribes<\/code>, <code>{prefix}flexa_blocked_emails<\/code>, <code>{prefix}flexa_unsubscribe_reasons<\/code> (the last seeded with three default reasons).<\/li>\n<li>Visit <strong>Unsubscribe<\/strong> in the admin sidebar to configure.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20to%20change%20anything%20in%20my%20existing%20email%20sending%20code%3F\"><h3>Do I need to change anything in my existing email sending code?<\/h3><\/dt>\n<dd><p>No. The plugin hooks <code>wp_mail<\/code> with standard WordPress filters. Any plugin or theme that sends mail via <code>wp_mail<\/code> is covered automatically.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20i%20rotate%20%60auth_key%60%3F\"><h3>What happens if I rotate `AUTH_KEY`?<\/h3><\/dt>\n<dd><p>Every in-flight unsubscribe\/resubscribe link becomes invalid, because the HMAC key is <code>AUTH_KEY<\/code>. New links issued after rotation work normally. Existing records in the database are unaffected.<\/p><\/dd>\n<dt id=\"how%20are%20blocked%20emails%20different%20from%20unsubscribed%20addresses%3F\"><h3>How are blocked emails different from unsubscribed addresses?<\/h3><\/dt>\n<dd><p>Unsubscribes is the list of addresses that opted out. <code>Blocked emails<\/code> is the audit log of outgoing sends that were stopped because they targeted an unsubscribed address. One unsubscribe can cause many blocked-email entries over time.<\/p><\/dd>\n<dt id=\"are%20csv%20exports%20safe%20to%20share%20publicly%3F\"><h3>Are CSV exports safe to share publicly?<\/h3><\/dt>\n<dd><p>No \u2014 CSV exports contain email addresses. Treat them as PII. The download link is nonce-protected so it's not trivially shareable across sessions.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>3.0.2<\/h4>\n\n<ul>\n<li><strong>Security:<\/strong> Sanitize <code>$_GET['email']<\/code> and <code>$_GET['token']<\/code> at the read site in the public unsubscribe\/resubscribe handler (<code>sanitize_email<\/code> \/ <code>sanitize_text_field<\/code> + <code>wp_unslash<\/code>), with a documented <code>phpcs:disable WordPress.Security.NonceVerification.Recommended<\/code> since the HMAC token is the CSRF protection layer for these public links.<\/li>\n<li><strong>Compatibility:<\/strong> Replace inline <code>&lt;style&gt;<\/code> and <code>&lt;script&gt;<\/code> blocks in <code>templates\/unsubscribe-page.php<\/code> and <code>templates\/resubscribe-page.php<\/code> with <code>wp_register_style<\/code> \/ <code>wp_enqueue_style<\/code> \/ <code>wp_add_inline_style<\/code> (and the script equivalents), so the public templates pass the WP.org Plugin Check enqueue rule.<\/li>\n<li><strong>Docs:<\/strong> Fix the source-code repository URL in <code>readme.txt<\/code>.<\/li>\n<\/ul>\n\n<h4>3.0.0<\/h4>\n\n<ul>\n<li><strong>Complete admin rewrite.<\/strong> The seven admin pages are now a React single-page app (Vite + TypeScript + shadcn\/ui + Tailwind v4) instead of individual PHP-rendered screens.<\/li>\n<li><strong>New:<\/strong> REST API under <code>\/wp-json\/flexa-unsubscribe\/v1\/<\/code> covering unsubscribes, blocked emails, re-subscribes, reasons, settings, appearance, and analytics. Every admin screen consumes this API.<\/li>\n<li><strong>New:<\/strong> Dashboard with time-series and reasons charts (recharts).<\/li>\n<li><strong>New:<\/strong> Live preview panel on the Appearance screen \u2014 see your colors, fonts, and copy applied to a replica of the public unsubscribe page while you edit.<\/li>\n<li><strong>New:<\/strong> Client-side search + server-side sort + server-side pagination on every list screen.<\/li>\n<li><strong>New:<\/strong> URL-synced table state (<code>?page=2&amp;sort=email&amp;order=desc<\/code> bookmarkable) on every list screen.<\/li>\n<li><strong>Security:<\/strong> CSV export <code>admin-post.php<\/code> handlers now verify nonces via <code>check_admin_referer()<\/code>.<\/li>\n<li><strong>Change:<\/strong> Admin menu label is \"Unsubscribe\" (same as pre-2.x) and sits at menu position 60. Slug changed from <code>flexa-su<\/code> to <code>flexa-unsubscribe<\/code> \u2014 legacy admin bookmarks will 404.<\/li>\n<li><strong>Change:<\/strong> Removed the <code>flexa_get_analytics_data<\/code> AJAX endpoint, superseded by the REST <code>\/analytics\/*<\/code> routes.<\/li>\n<li><strong>Requires PHP 7.4<\/strong> (was previously unspecified; the plugin now declares the floor).<\/li>\n<\/ul>\n\n<h4>2.0.2<\/h4>\n\n<ul>\n<li>Pagination for large lists.<\/li>\n<\/ul>\n\n<h4>2.0.1<\/h4>\n\n<ul>\n<li>Menu refinements.<\/li>\n<\/ul>\n\n<h4>2.0.0<\/h4>\n\n<ul>\n<li>Analytics page introduced.<\/li>\n<\/ul>","raw_excerpt":"Professional email unsubscribe management with HMAC tokens, auto-appended unsubscribe links, recipient blocking, and CSV export.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/305905","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=305905"}],"author":[{"embeddable":true,"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/flexatech"}],"wp:attachment":[{"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=305905"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=305905"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=305905"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=305905"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=305905"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/fa.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=305905"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}