Specialized tool for managing J2Commerce privacy data, consent, and GDPR/DSGVO compliance tasks.

Install

mkdir -p .claude/skills/privacy-plugin && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/17403" && unzip -o skill.zip -d .claude/skills/privacy-plugin && rm skill.zip

Installs to .claude/skills/privacy-plugin

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Deep knowledge of the plg_privacy_j2commerce plugin. Use when working on GDPR/DSGVO compliance, retention logic, lifetime license detection, template integration, checkout consent, or data export/deletion.
205 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • →Export J2Commerce orders, addresses, and cart data
  • →Enforce configurable retention periods for data deletion
  • →Anonymize orders outside the retention period
  • →Detect lifetime licenses to preserve email after retention expires
  • →Add a consent checkbox to the J2Commerce checkout
  • →Run a scheduled automatic cleanup task

How it works

The plugin extends Joomla's `com_privacy` to handle J2Commerce-specific data, including exporting, enforcing retention, anonymizing orders, detecting lifetime licenses, adding checkout consent, and running cleanup tasks.

Inputs & outputs

You give it
Privacy export request, data deletion request, or checkout process
You get back
Exported J2Commerce data, anonymized orders, preserved emails, or recorded consent

When to use privacy-plugin

  • →Configure data retention policies
  • →Anonymize expired orders
  • →Integrate privacy consent at checkout
  • →Generate data export reports

About this skill

Privacy Plugin — Domain Knowledge

Location

j2commerce/plg_privacy_j2commerce/

What This Plugin Does

Extends Joomla's com_privacy with J2Commerce-specific data handling:

  • Exports J2Commerce orders and addresses, optional Joomla user/profile/action-log data, and AcyMailing subscriber data on privacy export requests
  • Carries out removal requests: deletes addresses, the carts of the account and AcyMailing data, anonymizes orders outside the retention period, keeps orders within it and reports them (administrator message, customer e-mail)
  • Anonymizes orders outside the retention period instead of deleting them (registered users and, via the task, guest orders)
  • Detects lifetime licenses: those orders keep only their order e-mail after the retention period (provisional, see Decisions)
  • Adds a consent checkbox to the J2Commerce checkout; on J2Commerce 6 validates it server-side and records one #__privacy_consents row per order (bundled system plugin)
  • Renders a self-service privacy tab in the J2Commerce MyProfile page (consent status, request buttons per option: com_privacy form for logged-in users, mailto: for guests)
  • Runs a scheduled automatic cleanup task

Key Files

FilePurpose
src/Extension/J2Commerce.phpMain plugin class — all event handlers
plugins/task/j2commerceprivacy/src/Extension/J2CommercePrivacy.phpScheduled cleanup task (separate task plugin)
plugins/system/j2commerceprivacy/src/Extension/J2CommercePrivacy.phponMailBeforeRendering: links the com_privacy administrator request mail to the confirmation page; checkout consent on J2Commerce 6 (onAfterRoute, onJ2CommerceAfterDisplayShippingPayment, onJ2CommerceCheckoutCleanup; records the consent on checkout.confirmPayment); bundled system plugin installed by script.php
src/Consent/ConsentRepository.php#__privacy_consents: one record per order without duplicates, status lookup by user_id or, for guests, only the order of the session token + e-mail
layouts/privacy_tab.phpPrivacy tab markup, rendered by the myprofile/default_privacy.php overrides
src/Frontend/PrivacyOptions.phpFrontend options for the MyProfile overrides (show_privacy_section, show_delete_address, show_export_data, show_delete_all), all off while the plugin is disabled; loads the plugin language
script.phpInstall/update/uninstall, post-install message
language/en-GB/plg_privacy_j2commerce.iniAll translatable strings

Events Handled

EventPurpose
onPrivacyExportRequestCollect J2Commerce data for export
onPrivacyCanRemoveDataDoes not block for retention reasons (orders within the retention period are kept and reported; lifetime-license orders keep only their e-mail, provisional); only exception: Joomla found an account of a different address (muller@ for müller@), see the e-mail comparison decision
onPrivacyRemoveDataAnonymize/delete data
onAjaxJ2commercePrivacyAddress deletion (task=deleteAddress, logged-in, JSON) and the confirmation page for privacy requests without login (task=confirmRequest, HTML); results go through $event->addResult(). The form token is checked by the plugin itself (hasValidToken(): X-CSRF-Token header, POST field or query parameter, as AJAX Forms), never with Session::checkToken(): for a request without session cookie that redirects with 303 to Route::_('index.php'), the router merges the com_ajax query into it with &, and every hop loops (dev check 13.10.2026). Plugin classes call Route::_() with xhtml=false; 04b checks both statically

See references/architecture.md for full details.

Decisions (maintainer, PR #187)

TopicDecision
CompatibilityJoomla 5.4 or later (5.4.x, 6.x), PHP 8.1+; no compatibility layer for Joomla 5.0 to 5.3. No dispatcher in plugin constructors or setDispatcher() in service providers (Joomla sets it on load)
Guest accessOne order token = exactly one order (native J2Commerce logic): the Privacy tab of a guest session shows only the order of guest_order_token + guest_order_email, never other orders of the same address
Checkout checkboxJ2Commerce 6: rendered by the system plugin through the core event AfterDisplayShippingPayment (J2Commerce 6.3.4 or later, installer warns for older versions); no J2Commerce 6 checkout override is shipped. Required only through the plugin options "Show Consent Checkbox" and "Consent Required". No cart (ID 0): not stored, a required consent is refused. Recorded only after J2Commerce accepted the order (capturePlacement() on checkout.confirmPayment with form token or gateway return GET, recordAcceptedOrderConsent() at shutdown: order exists, same cart, order_state_id != 5), once per order (removeDuplicateConsents())
IP address and user agentStored in the consent record as proof of consent and for shop security (legitimate interest; IP via IpHelper::getIp()). Removed when the order is anonymized, and by the task when the record is outside the retention period (10 years by default, from the end of the fiscal year in the site time zone) or its order was deleted or already anonymized (removeStaleEvidence()); the record stays as evidence without personal data
Retention periodCounted from the end of the fiscal year of the order (fiscal_year_end, default 12-31, OR Art. 958f) in the site time zone; the SQL cutoff is converted to UTC
Removal requestsNot refused (only exception: Joomla found an account of a different address (muller@ for müller@), see the e-mail comparison decision): everything not subject to a retention obligation is removed; orders within the retention period are kept and reported to the administrator and, by e-mail in the customer's language, to the customer
Lifetime licensesVariant A, provisional (confirmation pending): a removal request is carried out; after the retention period only the order e-mail of lifetime-license orders is kept (license reactivation); the same rule per order in the removal request and the task, fail-closed
Action logJoomla's action log (#__action_logs, e.g. login records) is separate: the plugin only exports it (include_joomla_data) and, with activity_logging, adds its own entries (with IP address); it never changes or deletes existing entries
OperatorsMust define the storage period of consent records and describe the stored data (IP address, user agent, order number, time), its purpose and storage period in their privacy policy; consent records without personal data are not deleted automatically
J2Commerce stackSupport\J2CommerceStack: the active shop (display, recording consent) is decided by the enabled component, the same rule as in all Advans J2Commerce extensions: com_j2commerce enabled with its tables → #__j2commerce_*; otherwise com_j2store enabled with its tables → #__j2store_*; an enabled component without tables is skipped, an installed but disabled one does not count; otherwise the J2Commerce 6 tables if they exist. Removal, anonymization, retention cleanup and export run on all existing sets (dataSets(), forEachDataSet() / task dataSetOverride), so migration copies in #__j2store_* are cleaned too
Legacy consentsRecords of the earlier advans template override (PLG_PRIVACY_J2COMMERCE, e-mail in the body, partly created afterwards) are never assigned to an order: only anonymized (anonymizeLegacyConsents(): installation and update for all accounts with an admin message, removal request scoped to the user plus guest records with the request/account e-mail, task; batches), subject PLG_SYSTEM_J2COMMERCEPRIVACY_CONSENT_SUBJECT_LEGACY, neutral body in the website's default site language (com_languages → site, fallback the packaged en-GB file, and if even that is missing the key itself is stored and the next unscoped run replaces it with the text) and state = -1 (invalid, hidden from the com_privacy lists), not shown or counted in the Privacy tab. The unscoped path also repairs bodies that an older version stored as the raw language key; a scoped removal request never touches another account's record
Guest requests (owner decision 2026-10-12)Export, retention check, anonymization, guest addresses and the guest consent export match the account (user_id) and guest records (user_id = 0) with the request or account e-mail (ownerCondition(), trimmed, case-insensitive, never another account, never [email protected]); user = null is processed by the request e-mail; guest carts are never touched. Guests confirm an administrator-created request on task=confirmRequest (e-mail + code, checks as com_privacy ConfirmModel, status 0 -> 1, super users + action log, expired matching code -> -1, failures limited in 15 min: 5 per session, 5 per address and 20 per client IP in the table #__privacy_j2commerce_attempts (Security\ConfirmAttempts, HMAC hashes with the site secret only, purged on write and by the task, created by manifest SQL plus a postflight backstop), uniform answer and work while blocked); the system plugin points {TOKENURL}/{FORMURL} of com_privacy.notification.admin.* there (relies on MailTemplate replacing tokenurl before token). Option guest_confirmation (default on)
E-mail comparison (finding 13.10.2026)Exact after ConsentRepository::normaliseAddress() (trim, Unicode lower case): SQL only preselects (addressPrefilter(): ASCII values by ASCII lower case under utf8mb4_bin / PostgreSQL "C", every value with non-ASCII characters as a candidate, so no database case table or locale loses a match; addressValues() reads in batches of BATCH_SIZE), PHP decides (addressValues(), normaliseAddress()), rows are then addressed by the exact stored value (exactValuesCondition(): `utf8mb

Content truncated.

When not to use it

  • →When working with general Joomla privacy features not specific to J2Commerce
  • →When the goal is to delete data immediately without retention period enforcement
  • →When the plugin's specific event handlers are not relevant

Limitations

  • →The plugin is specific to `plg_privacy_j2commerce`
  • →The plugin anonymizes orders instead of deleting them outside the retention period
  • →The plugin requires specific event handlers like `onPrivacyExportRequest` and `onPrivacyRemoveData`

How it compares

This plugin provides specialized privacy functionalities tailored for J2Commerce data, such as anonymizing orders and detecting lifetime licenses, which are not typically covered by generic privacy plugins.

Compared to similar skills

privacy-plugin side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
privacy-plugin (this skill)03moNo flagsIntermediate
command-injection-testing19moReviewAdvanced
file-upload-testing19moReviewAdvanced
security-hardening04moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry