Beskrivning
Article 7.1 of the GDPR demands more than a boolean: the defensible consent record needs the timestamp, the IP, the user agent, the document version in force at that moment and the exact text the user was shown.
Terms & Conditions Consent Log fills that gap for any acceptance checkbox on your site, with or without WooCommerce. Every accepted consent — at the WooCommerce checkout, in a Contact Form 7 form, in a WPForms form, in the WordPress comments form, on the WordPress / WooCommerce login or registration form, or in a stand-alone shortcode/block — writes a row to a dedicated indexed table, sealed with a SHA-256 hash of the accepted text so any later change is detectable. From a clean admin screen you can filter, search, export to CSV, integrate with the native WordPress Privacy Tools, and open a one-page printable A4 certificate per record (your browser saves it as PDF in one click).
Works with or without WooCommerce
The admin menu lives under Users Consent log on every install, with or without WooCommerce. The WooCommerce-specific bits (checkout capture, order metabox, ”Consent” column on the orders list, optional consent line in the order emails) load only when WooCommerce is active; everything else (Records, Settings, CSV export, PDF certificate, Privacy Tools integration) works the same way on any WordPress site.
Sources of consent
- WooCommerce checkout (auto when WC is active): captures the native terms checkbox.
- Contact Form 7 (auto): detects [acceptance] fields automatically and the first email field of the form. Stored as
cf7_form_{ID}, one type per form. No snippets required. On by default; turn off in Settings if it does not apply. - WPForms (auto): detects GDPR Agreement fields automatically and the first email field of the form. Stored as
wpforms_form_{ID}, one type per form. Works with WPForms Lite and Pro. No snippets required. On by default; turn off in Settings if it does not apply. - WordPress comments (auto): logs the native
wp-comment-cookies-consentcheckbox (introduced in WP 4.9.6) when the visitor opts in. Stored ascomment_consent. On by default; turn off in Settings if your site uses Disqus, Jetpack or another third-party comments system. - WordPress login and registration (auto): captures successful logins and registrations through wp-login.php when a consent checkbox is ticked on the form. Stored as
wp_loginandwp_register. Registration is on by default; login is off by default (a normal login form has no consent checkbox, so login only matters for re-consent flows). The ”Remember me” checkbox is excluded by design (ePrivacy / cookie preference, not GDPR consent). - WooCommerce login and registration (auto when WC is active): same idea for the My Account page. Stored as
wc_loginandwc_register. Registration is on by default; login is off by default, like the WordPress rows above. An opt-in toggle can inject the consent checkbox into the WC register form, since WooCommerce does not ship one natively. [tccl_consent_box]shortcode and Gutenberg block: drop a self-contained consent checkbox in any page, post or widget area as a stand-alone block. Submission posts to a REST endpoint and writes a record. Always available.
For anything else (Gravity Forms, Fluent Forms, Elementor Forms, Forminator, custom flows), call tccl_save_consent() from the appropriate hook.
Why a dedicated table
Storing thousands of consent records in wp_postmeta is wasteful and slow. The plugin uses its own indexed table and exposes a public function (tccl_save_consent) that you can call from anywhere to log additional consents in the same place.
Main features
- Records timestamp UTC, IP, user agent, document version, source URL and full consent text per acceptance.
- Custom database table with the right indexes (no
wp_postmetabloat). - Tamper-evident: each record is sealed with a SHA-256 hash. Any later change to the stored text is detected and reported as TAMPERED in the records list.
- Printable A4 certificate per record, with a built-in ”Print / Save as PDF” button — the browser exports the certificate to PDF natively, no external library bundled.
- Native Privacy Tools integration:
Tools > Export Personal DataandTools > Erase Personal Databoth include consent records (erasure anonymises rather than deletes — the record itself is the lawful basis to keep it). - WooCommerce checkout texts are optional — leave them empty and the WooCommerce native text is shown to the customer and stored verbatim.
- Automatic version bump when the text changes (suggests
MAJOR.MINOR-YYYY-MM-DD). - Optional opt-out of IP and/or user agent tracking.
- Configurable retention with a one-click anonymise button (records kept; PII scrubbed).
- Live partial-match filters (email, order, date range, type, full-text search inside the accepted text) + filtered CSV export with UTF-8 BOM (opens cleanly in Excel).
- (When WooCommerce is active) Order metabox with the consent summary, integrity badge and outdated-version indicator. ”Consent” column on the orders list (legacy and HPOS) with a quick visual status. Optional consent line in the New order email (admin) and the order confirmation email (customer) — both off by default.
- Optional
delete_data_on_uninstallsetting (off by default) — uninstalling does not destroy consent evidence unless you explicitly opt in. - HPOS (custom order tables) compatible.
- Public
tccl_save_consent()function to log consents from anywhere.
Translation ready
All strings use the terms-conditions-consent-log text domain. Translations are managed through translate.wordpress.org.
Support
Need help or have suggestions?
Love the plugin? Please leave us a 5-star review and help spread the word!
About AyudaWP.com
We are specialists in WordPress security, SEO, AI and performance optimization plugins. We create tools that solve real problems for WordPress site owners while maintaining the highest coding standards and accessibility requirements.
Skärmdumpar

Records list with live filters, integrity column and CSV export. 
Settings tab with editable texts, version control, retention, email options and uninstall control. 
Order metabox with consent summary, integrity badge and printable-certificate button. 
Consent column on the orders list. 
Printable A4 certificate ready to be saved as PDF from the browser. 
Exported CSV file with filtered records (metadata header + nice column names).
Block
Detta tillägg tillhandahåller 1 block.
- Consent box A self-contained consent checkbox that records each acceptance in the consent log.
Installation
- Upload the plugin folder to
/wp-content/plugins/terms-conditions-consent-log/or install through Plugins > Add New. - Activate the plugin.
- Open the plugin admin page: Users > Consent log.
- In the Settings tab, the integrations (WordPress comments, Contact Form 7, WPForms, WP/WooCommerce registration) are on by default to support GDPR Article 7.1 (proof of consent) — turn off any that do not apply to your site. Login capture is off by default and only needs turning on if your login form carries a consent checkbox (for example a re-consent prompt). You can also paste
[tccl_consent_box]in any page or post. - (Optional, WooCommerce only) Override the checkbox text or add a pre-checkout informational paragraph. Leave them empty to keep the WooCommerce native text.
- Every accepted consent from any of the enabled sources will be logged automatically from now on.
Vanliga frågor
-
Can I use the plugin without WooCommerce?
-
Yes. Activate it on any WordPress site and the Records, Settings, CSV export, PDF certificate and Privacy Tools integration all work the same way. The WooCommerce-specific bits (checkout capture, order metabox, order list column, order email line) only load when WooCommerce is active.
-
How do I capture consents from Contact Form 7?
-
Open Consent log > Settings > Integrations and tick ”Log every CF7 form submission that ticks an [acceptance] field”. Then make sure your CF7 forms include an [acceptance] field, e.g.:
[acceptance privacy] I have read and agree to the privacy policy. [/acceptance]The plugin uses the form ID as part of the consent_type (cf7_form_{ID}), so each form is filterable separately. The first email field of the form is used as the subject email. No snippets, no functions.php edits.
-
How do I capture consents from WPForms?
-
Open Consent log > Settings > Integrations and tick ”Log every WPForms submission that ticks a GDPR Agreement field”. Then add a GDPR Agreement field to your form from the WPForms builder (Fancy Fields GDPR Agreement) and edit its label to the exact wording you want recorded (e.g. ”I have read and agree to the privacy policy.”).
The plugin uses the form ID as part of the consent_type (wpforms_form_{ID}), so each form is filterable separately. The first email field of the form is used as the subject email, and the GDPR Agreement field label is what gets stored as the accepted text. Works with WPForms Lite and Pro. No snippets, no functions.php edits.
-
How does the [tccl_consent_box] shortcode work?
-
It renders a self-contained consent checkbox + submit button, with optional email field for visitors who are not logged in. Submission posts to a REST endpoint that records the consent through tccl_save_consent(). Drop it in any page, post or widget area as a stand-alone block, e.g.:
[tccl_consent_box text="I have read and agree to the privacy policy." consent_type="newsletter_signup"]The same functionality is also available as a Gutenberg block called ”Consent box”.
Important: the shortcode renders its own
<form>with a submit button, so it should NOT be nested inside another form builder’s form (Contact Form 7, WPForms, Gravity Forms, Fluent Forms, Elementor Forms, etc.). If you embed it inside another form you will end up with two submit buttons and conflicting submit flows. For form builders, use the dedicated integration (Contact Form 7 and WPForms are built in; for the rest, hook tccl_save_consent() from the relevant submission action — see the Gravity Forms / Fluent Forms FAQ below).Also: do NOT use this shortcode as a substitute for the cookie checkbox of a cookie/banner plugin (Complianz, CookieYes, Real Cookie Banner, etc.). The legal context is different — cookie banners cover ePrivacy/cookies, this consent log covers GDPR art. 7.1 specific consents to specific personal-data processing. Mixing them yields ambiguous evidence.
-
How are WordPress and WooCommerce login / registration consents logged?
-
The plugin hooks into the standard
wp_loginevent (which covers both wp-login.php and the WooCommerce My Account login) and into the public registration events (register_new_userfor the WP form andwoocommerce_created_customerfor the WC form). For each event, it inspects the submission$_POSTfor a ticked consent checkbox and, if one is present, writes a record withconsent_typeset towp_login,wp_register,wc_loginorwc_registeraccordingly.A few specifics worth knowing:
- ”Remember me” is excluded by design. It is an ePrivacy preference about extending the session cookie, not a GDPR Article 7.1 consent. Logging it would contaminate the audit trail with non-consent events. The exclusion is hard-coded.
- No checkbox in the form, no record. The plugin does not log ”raw logins” — it only writes a row when there is something resembling an explicit consent checkbox to record. A login or registration without a consent field never produces a record.
- The detector is heuristic. Field names containing
consent,gdpr,privacy,terms,acceptance,agreement,accept,rgpd,politica,privacidadorterminos(case-insensitive) are treated as the consent checkbox. If your GDPR / privacy plugin uses a different name, list it in Settings Integrations ”Custom consent field names” (comma-separated, exact match). - The injected checkbox option fills the WooCommerce gap. WooCommerce does not include a consent checkbox in its register form out of the box — only a privacy-policy paragraph. If your site does not run a separate GDPR plugin, enable ”Add a required consent checkbox to the WooCommerce registration form” in Settings; the plugin will render the checkbox above the submit button and reject the registration if it is left unticked. The same option exists for the WP register form.
- Social logins are not captured. Plugins like Nextend Social Login bypass the WP login form entirely (OAuth callback), so there is no submission
$_POSTfor the detector to inspect. Use the publictccl_save_consent()function from the social plugin’s own ”after login” hook if you need that coverage. - The stored
consent_textcomes from Settings. Paste in ”Consent text for login / registration” the exact wording that the visitor sees on the form (whether it comes from your GDPR plugin or from the injected checkbox), so the record reflects what was actually shown. HTML is allowed in that field, so you can include a link to your privacy policy.
-
Are WordPress comment opt-ins logged automatically?
-
Yes, by default. Only comments where the visitor ticks the native ”Save my name, email, and website…” checkbox are recorded. You can opt out in Consent log > Settings > Integrations if your site uses Disqus, Jetpack Comments or any other third-party comments system where the native checkbox is not rendered.
-
Does it work with the new WooCommerce Block Checkout?
-
Not yet. The classic checkout is fully supported. Block Checkout support is on the roadmap.
-
Where is the data stored?
-
In a custom indexed table called
wp_tccl_consents(with your site prefix). When WooCommerce is active, each order also gets three meta entries (_tccl_terms_accepted,_tccl_terms_version,_tccl_recorded_at) so the order edit screen can show the summary without querying the table. -
How do I bump the document version when I change my terms?
-
Edit the version field in Consent log > Settings, or simply check ”Bump version on save”. The plugin can also bump it automatically if it detects the checkbox text has changed but the version field has not.
Three things to keep in mind:
- The version string in Settings must match the version label of your terms document character by character (e.g.
1.1-2026-05-17). It is a free-text identifier and the plugin just compares strings, so a trailing space or a different separator will be treated as a different version. - Once you bump the version, every record stored under the previous version is automatically flagged as ”Outdated” in the records list. This is on purpose — it is the GDPR audit trail showing which exact wording each subject accepted at that moment. ”Outdated” is a feature, not a bug.
- Do NOT delete or ”clean up” Outdated records. They are the legal proof of consent for the version that was in force when the subject accepted it. If the user retires the terms and a regulator later asks for evidence, those rows are what you show them.
- The version string in Settings must match the version label of your terms document character by character (e.g.
-
How do I delete or anonymise data for a specific customer?
-
Use the WordPress native Tools > Erase Personal Data screen. The plugin registers an eraser that anonymises records linked to the requested email (it does not delete them, since the record itself is the lawful basis to keep the proof of consent). You can also anonymise filtered records from the Records tab.
-
How do I export a customer’s consent history?
-
Use Tools > Export Personal Data. The plugin registers an exporter that returns every consent record linked to the requested email.
-
Will an uninstall destroy my data?
-
Only if you explicitly opt in. The setting ”Delete all data on uninstall” is off by default. Even if you uninstall accidentally, your consent evidence will survive.
If you need to clean up a handful of test rows you generated while configuring the plugin (and you do not yet have the upcoming bulk-delete UI), you can remove them with a direct SQL statement against the consent table, e.g.:
DELETE FROM wp_tccl_consents WHERE id IN (1, 2, 3);Replace
wp_with your site’s actual table prefix. This is an escape hatch for legitimate clean-up after a misconfigured form; it is not a recommended day-to-day flow — to handle real subject requests, use Tools > Erase Personal Data (anonymises) instead. -
How do I capture consents from Gravity Forms, Fluent Forms or any other source?
-
Call the public
tccl_save_consent()function from the relevant hook. Always read the document version from the plugin setting (tccl_get_setting( 'consent_version', '1.0' )) so all records line up with the current version in Settings — if you hardcode a date here that differs from the one in Settings, every record will be flagged as ”Outdated” forever.Example for Gravity Forms:
add_action( 'gform_after_submission', function ( $entry, $form ) { if ( ! empty( $entry['1.1'] ) ) { // ID of your consent checkbox in the entry. tccl_save_consent( array( 'email' => sanitize_email( $entry['2'] ?? '' ), 'consent_type' => 'gravity_form_' . absint( $form['id'] ), 'consent_version' => tccl_get_setting( 'consent_version', '1.0' ), 'consent_text' => 'I have read and agree to the privacy policy.', 'consent_value' => 1, ) ); } }, 10, 2 );Same idea for
fluentform/submission_inserted,user_register,forminator_custom_form_after_submission,elementor_pro/forms/new_record, etc. — adapt the callback signature to each plugin’s documented arguments. WPForms and Contact Form 7 are captured automatically when their integration toggle is enabled in Settings Integrations; no snippet is needed for those two. -
Does the IP detection work behind Cloudflare or other reverse proxies?
-
The plugin reads
REMOTE_ADDRonly and does not trust forwarded headers, which can be spoofed without a verified proxy. If your hosting puts the proxy IP inREMOTE_ADDRinstead of the real client IP, all entries will record the proxy IP. Most WordPress-friendly hostings pass the real IP correctly. -
What does ”Tamper-evident” mean here?
-
When a consent is written, the plugin computes a SHA-256 hash of the exact accepted text and stores it alongside the record. On every read, the stored hash is compared against a freshly computed one — any difference is reported as TAMPERED in the records list, the order metabox and the certificate view. This is a cryptographic integrity check, not an electronic signature.
-
Is the certificate a real PDF?
-
The plugin renders a one-page A4 view with print-optimised CSS and a ”Print / Save as PDF” button. Modern browsers (Chrome, Safari, Firefox, Edge) export that view to a real PDF natively — same fidelity as a server-side library would produce, with the added benefit that it respects your site’s language and fonts. No external library bundled, so the plugin stays small.
To be clear: the plugin does NOT store any PDFs on disk and does NOT create an uploads folder of its own. The certificate is generated on demand as HTML each time you open it, and only becomes a PDF if you (or the customer) clicks ”Print / Save as PDF” in the browser. There is nothing to clean up on the server. If the site has a Site Icon defined in Settings > General (the same option block themes and classic themes share), it is shown in the certificate header next to the site name — including on certificates of consents recorded before this version, since the icon is added at render time, not at storage time.
Recensioner
Bidragsgivare och utvecklare
”Terms & Conditions Consent Log” är programvara med öppen källkod. Följande personer har bidragit till detta tillägg.
Bidragande personer”Terms & Conditions Consent Log” har översatts till 1 språk. Tack till översättarna för deras bidrag.
Översätt ”Terms & Conditions Consent Log” till ditt språk.
Intresserad av programutveckling?
Läs programkoden, kika på SVN-filförvaret eller prenumerera på utvecklarloggen via RSS.
Ändringslogg
1.4.0
- New: native WordPress login integration. Captures successful logins through wp-login.php as
consent_type = wp_loginwhenever the submission carries a ticked consent checkbox. The ”Remember me” checkbox is excluded by design — it is an ePrivacy / persistent-cookie preference, not a GDPR Article 7.1 consent. Opt-in toggle in Settings Integrations, off by default in fresh installs (a normal login form has no consent checkbox, so logging every login would only add noise). - New: native WordPress registration integration. Captures registrations through wp-login.php?action=register as
consent_type = wp_registerwhenever the registration form carries a ticked consent checkbox. Opt-in toggle, on by default in fresh installs. - New: native WooCommerce login integration. Captures the My Account login as
consent_type = wc_login. Routed by inspecting the submission for WC-specific markers and the HTTP referer, so it is reliably distinguished from the WP-admin login that shares the same underlying hook. - New: native WooCommerce registration integration. Captures customer creations through the My Account register form as
consent_type = wc_register, with email + source URL. - New: optional ”Inject a required consent checkbox” toggle for both the WP and the WC registration forms. WooCommerce does not ship a consent checkbox out of the box (only a privacy-policy paragraph), so this option fills that gap for sites without a separate GDPR plugin. The injected checkbox blocks the registration on the server side if it is left unticked.
- New: configurable ”Consent text for login / registration” (used as the stored
consent_texton every login/registration record, and also as the label of the injected checkbox). - New: configurable ”Custom consent field names” — a comma-separated list that overrides the built-in name heuristic for sites whose GDPR plugin uses unusual field names.
- New: heuristic detector for consent checkboxes. Names containing
consent,gdpr,privacy,terms,acceptance,agreement,accept,rgpd,politica,privacidadorterminosare treated as the consent checkbox (case-insensitive).remembermeand standard nonce / referer keys are always excluded.
For older changelog entries, please check the changelog.txt file.
