{"id":366019,"date":"2026-09-10T22:19:18","date_gmt":"2026-09-10T22:19:18","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/digital-product-passport-for-woocommerce\/"},"modified":"2026-09-10T22:18:56","modified_gmt":"2026-09-10T22:18:56","slug":"digital-product-passport-for-woocommerce","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/digital-product-passport-for-woocommerce\/","author":23306166,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.6.3","stable_tag":"1.6.3","tested":"7.1","requires":"6.4","requires_php":"8.0","requires_plugins":null,"header_name":"Digital Product Passport for WooCommerce","header_author":"AOS-Digital","header_description":"ESPR-compliant Digital Product Passports for WooCommerce \u2013 add product sustainability data, QR codes, and structured data to meet EU Regulation 2024\/1781.","assets_banners_color":"0c3a38","last_updated":"2026-09-10 22:18:56","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/aos-digital.de\/plugin-verzeichnis\/digital-product-passport","header_author_uri":"https:\/\/aos-digital.de","rating":0,"author_block_rating":0,"active_installs":0,"downloads":41,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.6.3":{"tag":"1.6.3","author":"aosdigital","date":"2026-09-10 22:18:56","revision":3690578}},"upgrade_notice":{"1.5.0":"<p>Recommended update: fixes a fatal activation error in the Pro add-on and resolves all Plugin Check compliance issues.<\/p>","1.2.0":"<p>Major update: new ESPR fields, new QR code provider, completeness score, display mode settings. Review your passport data after upgrading.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3690580,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3690580,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3690580,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3690580,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.6.3"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3690580,"resolution":"1","location":"assets","locale":"","width":1280,"height":1900},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3690580,"resolution":"2","location":"assets","locale":"","width":1280,"height":1420},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3690580,"resolution":"3","location":"assets","locale":"","width":1280,"height":760},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3690580,"resolution":"4","location":"assets","locale":"","width":1280,"height":1145},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3690580,"resolution":"5","location":"assets","locale":"","width":1280,"height":1100},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3690580,"resolution":"6","location":"assets","locale":"","width":375,"height":812}},"screenshots":{"1":"Digital Passport tab in WooCommerce product editor \u2014 with completeness bar","2":"Frontend modal showing full passport with QR code","3":"Material composition grid with recycled content column","4":"Settings page \u2014 display mode, REST API, and the sidebar pointing to the free add-on","5":"REST API JSON-LD response in browser","6":"Mobile bottom-sheet view of the passport modal"}},"plugin_section":[],"plugin_tags":[246982,246984,1373,155990,286],"plugin_category":[45],"plugin_contributors":[264317],"plugin_business_model":[],"class_list":["post-366019","plugin","type-plugin","status-publish","hentry","plugin_tags-digital-product-passport","plugin_tags-espr","plugin_tags-qr-code","plugin_tags-sustainability","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-aosdigital","plugin_committers-aosdigital"],"banners":{"banner":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/banner-772x250.png?rev=3690580","banner_2x":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/banner-1544x500.png?rev=3690580","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/icon-128x128.png?rev=3690580","icon_2x":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/icon-256x256.png?rev=3690580","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/screenshot-1.png?rev=3690580","caption":"Digital Passport tab in WooCommerce product editor \u2014 with completeness bar"},{"src":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/screenshot-2.png?rev=3690580","caption":"Frontend modal showing full passport with QR code"},{"src":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/screenshot-3.png?rev=3690580","caption":"Material composition grid with recycled content column"},{"src":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/screenshot-4.png?rev=3690580","caption":"Settings page \u2014 display mode, REST API, and the sidebar pointing to the free add-on"},{"src":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/screenshot-5.png?rev=3690580","caption":"REST API JSON-LD response in browser"},{"src":"https:\/\/ps.w.org\/digital-product-passport-for-woocommerce\/assets\/screenshot-6.png?rev=3690580","caption":"Mobile bottom-sheet view of the passport modal"}],"raw_content":"<!--section=description-->\n<p><strong>Digital Product Passport for WooCommerce<\/strong> adds the product data the EU Ecodesign for Sustainable Products Regulation (ESPR \/ EU 2024\/1781) asks for, and publishes it three ways: as a passport people can open on the product page, as a QR code that links to it, and as JSON-LD a machine can read through the REST API.<\/p>\n\n<p>Starting in 2025, the ESPR regulation requires many product categories sold in the EU to carry a Digital Product Passport covering sustainability, material composition, repairability, and end-of-life information. This plugin helps you meet those requirements today.<\/p>\n\n<h4>Key Features<\/h4>\n\n<ul>\n<li><strong>Full ESPR \/ EU 2024\/1781 Compliance<\/strong> \u2014 all mandatory data fields included<\/li>\n<li><strong>QR Code Generation<\/strong> \u2014 one code per product, generated inside the plugin as SVG. No external service, no API key, nothing leaves the site<\/li>\n<li><strong>GS1 Digital Link<\/strong> \u2014 QR codes follow the <code>\/01\/{gtin}\/21\/{serial}<\/code> standard<\/li>\n<li><strong>JSON-LD Structured Data<\/strong> \u2014 schema.org + W3ID DPP ontology (<code>https:\/\/w3id.org\/dpp\/<\/code>)<\/li>\n<li><strong>REST API<\/strong> \u2014 GET <code>\/wp-json\/dpp\/v1\/passport\/{id}<\/code> with HTTP caching headers<\/li>\n<li><strong>Tab or Button Display<\/strong> \u2014 show the passport in a product tab or via a modal button<\/li>\n<li><strong>Completeness Score<\/strong> \u2014 live progress bar showing how complete each passport is<\/li>\n<li><strong>WooCommerce HPOS Ready<\/strong> \u2014 compatible with High Performance Order Storage<\/li>\n<li><strong>Cart &amp; Checkout Blocks<\/strong> \u2014 full Block Editor compatibility declared<\/li>\n<li><strong>Fully Translatable<\/strong> \u2014 all strings use the <code>digital-product-passport-for-woocommerce<\/code> text domain<\/li>\n<\/ul>\n\n<h4>Passport Data Fields<\/h4>\n\n<p><strong>Identity &amp; Traceability<\/strong>\n- GTIN \/ EAN-13 barcode\n- Serial number &amp; batch number\n- Brand name &amp; manufacturer name\n- Manufacturer address\n- Production country &amp; production date<\/p>\n\n<p><strong>Sustainability &amp; Environmental Impact<\/strong>\n- Carbon footprint (kg CO\u2082eq) + measurement methodology\n- Energy efficiency class (A+++ to G)\n- Material composition (name, % weight, % recycled content)\n- Recyclability percentage\n- Recycling instructions \/ end-of-life info<\/p>\n\n<p><strong>Repairability &amp; Durability<\/strong>\n- Repairability index (0\u201310)\n- Spare parts availability &amp; availability period\n- Durability \/ expected lifespan (years)\n- Warranty duration (months)\n- Repairability documentation available (yes\/no)<\/p>\n\n<p><strong>Compliance<\/strong>\n- Substances of concern (REACH \/ RoHS)\n- Applicable regulation reference\n- Compliance document URL<\/p>\n\n<h4>Free add-on<\/h4>\n\n<p>Nothing in this plugin is locked or limited. Everything described above works, for every\nproduct, with no key and no account.<\/p>\n\n<p>A separate add-on, also free, adds work that only larger catalogues need. It is a second\nplugin you download from us; this one does not change when you install it, it simply\nfinds it:<\/p>\n\n<ul>\n<li><strong>Analytics Dashboard<\/strong> \u2014 track passport views per product with Chart.js charts<\/li>\n<li><strong>PDF Passport Export<\/strong> \u2014 print-optimized HTML passport with your branding<\/li>\n<li><strong>Bulk Passport Editor<\/strong> \u2014 edit all products in a spreadsheet-like grid<\/li>\n<li><strong>CSV &amp; JSON Import\/Export<\/strong> \u2014 migrate data or sync with external systems<\/li>\n<li><strong>Email Notifications<\/strong> \u2014 notify admins on passport updates + weekly digest reports<\/li>\n<li><strong>ACF Integration<\/strong> \u2014 sync Advanced Custom Fields with passport data<\/li>\n<li><strong>WPML &amp; Polylang Support<\/strong> \u2014 multilingual passport data<\/li>\n<li><strong>Branded PDFs<\/strong> \u2014 custom logo, company name, and accent color in exports<\/li>\n<\/ul>\n\n<h3>Developer Hooks<\/h3>\n\n<h4>Actions<\/h4>\n\n<ul>\n<li><code>dpp_passport_saved( $product_id )<\/code> \u2014 fired after passport data is saved<\/li>\n<li><code>dpp_passport_viewed( $product_id )<\/code> \u2014 fired when a passport is viewed (used by Pro analytics)<\/li>\n<li><code>dpp_passport_content_end( $product_id )<\/code> \u2014 fired at the end of passport content (used by Pro PDF button)<\/li>\n<li><code>dpp_before_passport_display( $product_id )<\/code> \u2014 before passport HTML output<\/li>\n<li><code>dpp_after_passport_display( $product_id )<\/code> \u2014 after passport HTML output<\/li>\n<\/ul>\n\n<h4>Filters<\/h4>\n\n<ul>\n<li><code>dpp_passport_data( $data, $product_id )<\/code> \u2014 modify passport data array before display<\/li>\n<li><code>dpp_json_ld_output( $json_ld, $product_id )<\/code> \u2014 modify JSON-LD structured data<\/li>\n<li><code>dpp_qr_code_url( $url, $product_id )<\/code> \u2014 modify QR code URL<\/li>\n<li><code>dpp_rest_passport_response( $response, $product_id )<\/code> \u2014 modify REST API response<\/li>\n<\/ul>\n\n<h4>REST API<\/h4>\n\n<ul>\n<li><code>GET \/wp-json\/dpp\/v1\/passport\/{id}<\/code> \u2014 passport by product ID<\/li>\n<li><code>GET \/wp-json\/dpp\/v1\/passport\/gtin\/{gtin}<\/code> \u2014 passport by GTIN<\/li>\n<li><code>GET \/wp-json\/dpp\/v1\/passports?search={term}&amp;per_page={n}<\/code> \u2014 search passports (max 100)<\/li>\n<\/ul>\n\n<h3>Support<\/h3>\n\n<ul>\n<li>Documentation: <a href=\"https:\/\/aos-digital.de\/plugin-verzeichnis\/digital-product-passport\">aos-digital.de\/plugin-verzeichnis\/digital-product-passport<\/a><\/li>\n<li>Support: support@aos-digital.de<\/li>\n<li>Issues: support@aos-digital.de<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin to <code>\/wp-content\/plugins\/digital-product-passport-for-woocommerce\/<\/code> or install via the WordPress plugin directory<\/li>\n<li>Activate through the <strong>Plugins<\/strong> menu<\/li>\n<li>Ensure WooCommerce 8.0+ is installed and active<\/li>\n<li>Navigate to any product edit page \u2014 a <strong>Digital Passport<\/strong> tab appears in the product data panel<\/li>\n<li>Fill in at least the manufacturer name and save<\/li>\n<\/ol>\n\n<h4>Requirements<\/h4>\n\n<ul>\n<li>WordPress 6.4 or higher<\/li>\n<li>WooCommerce 8.0 or higher<\/li>\n<li>PHP 8.0 or higher<\/li>\n<\/ul>\n\n<!--section=faq-->\n<dl>\n<dt id=\"is%20this%20plugin%20gdpr%20compliant%3F\"><h3>Is this plugin GDPR compliant?<\/h3><\/dt>\n<dd><p>All passport data stays in your WordPress database, and the plugin contacts no external service at all \u2014 QR codes are generated on your own server. No analytics, no telemetry, nothing sent anywhere. Whether your site as a whole is GDPR compliant depends on the rest of it, but this plugin adds no data flow you would have to declare.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20variable%20products%3F\"><h3>Does it work with variable products?<\/h3><\/dt>\n<dd><p>Yes. Each product (including variations) can have its own complete passport. HPOS and legacy order storage are both supported.<\/p><\/dd>\n<dt id=\"how%20are%20qr%20codes%20generated%3F\"><h3>How are QR codes generated?<\/h3><\/dt>\n<dd><p>Inside the plugin, with no network request. The encoder writes the symbol as SVG and stores it in your uploads folder so the work is done once per product. Addresses longer than 213 characters do not fit a version 10 symbol; there you get a visible note instead of an unreadable code.<\/p><\/dd>\n<dt id=\"can%20i%20customize%20the%20display%3F\"><h3>Can I customize the display?<\/h3><\/dt>\n<dd><p>Yes. Use the <code>display_position<\/code> setting to choose between a modal button or an inline product tab. CSS custom properties (<code>--dpp-primary<\/code>, <code>--dpp-radius<\/code>, etc.) let you restyle without editing plugin files. The add-on adds PDF branding options.<\/p><\/dd>\n<dt id=\"what%20shortcodes%20are%20available%3F\"><h3>What shortcodes are available?<\/h3><\/dt>\n<dd><ul>\n<li><code>[dpp_button]<\/code> \u2014 renders the \"View Passport\" button<\/li>\n<li><code>[dpp_passport]<\/code> \u2014 renders the full passport inline<\/li>\n<li><code>[dpp_qr_code]<\/code> \u2014 renders the product's QR code<\/li>\n<\/ul>\n\n<p>All shortcodes accept a <code>product_id<\/code> attribute. When omitted, the current product is used.<\/p><\/dd>\n<dt id=\"is%20the%20rest%20api%20public%3F\"><h3>Is the REST API public?<\/h3><\/dt>\n<dd><p>GET requests to <code>\/wp-json\/dpp\/v1\/passport\/{id}<\/code> are public by default (configurable in settings). The API returns JSON-LD with <code>Cache-Control<\/code> and <code>X-Robots-Tag: noindex<\/code> headers.<\/p><\/dd>\n<dt id=\"does%20it%20support%20hpos%3F\"><h3>Does it support HPOS?<\/h3><\/dt>\n<dd><p>Yes. The plugin explicitly declares <code>custom-order-tables<\/code> compatibility, so it works whether you use HPOS or the legacy posts table.<\/p><\/dd>\n<dt id=\"how%20does%20the%20completeness%20score%20work%3F\"><h3>How does the completeness score work?<\/h3><\/dt>\n<dd><p>Ten key fields are checked (manufacturer name, GTIN, country, CO\u2082, energy class, materials, recyclability, repair index, warranty, compliance). Each filled field adds weight to the score displayed as a progress bar in the product panel.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.6.3<\/h4>\n\n<ul>\n<li><strong>Fixed: the passport button did nothing, and several admin controls were dead.<\/strong> The prefix rename in 1.6.1 renamed the stylesheet and the scripts but not the class names that PHP prints into the markup. Twenty-two class names went out as <code>dpp-*<\/code> while the CSS and the JavaScript listened for <code>dppass-*<\/code>. The visible result: clicking \"Digital Product Passport\" on a product page opened nothing, and in the admin the buttons for adding and removing a material, opening the material library, saving and applying the company profile, the template buttons and the supplier edit and delete buttons had no handler. Everything is on one prefix now.<\/li>\n<li><strong>Fixed: three links in the admin led to a page that does not exist.<\/strong> The menu slugs are registered as <code>dppass-settings<\/code> and <code>dppass-upgrade<\/code>, but the \"Settings\" link WordPress shows next to the plugin, the add-on button in the settings sidebar and the link from the AOS Hub all pointed at <code>dpp-settings<\/code> and <code>dpp-upgrade<\/code>.<\/li>\n<li><strong>Fixed: decimal numbers on the passport always used English separators.<\/strong> The material shares, the carbon footprint, the repair index and the recyclability figure went through <code>number_format()<\/code>, which is not locale-aware. A German or French visitor saw 12.40 where 12,40 belongs. Now <code>number_format_i18n()<\/code>. The REST and JSON-LD output is untouched and stays machine-readable.<\/li>\n<li>Neither of these was caught by Plugin Check, PHPCS or PHPStan: none of them looks at CSS class names, and a link to a missing admin page is valid PHP. They were found by taking screenshots of the plugin in a browser.<\/li>\n<\/ul>\n\n<h4>1.6.2<\/h4>\n\n<ul>\n<li><strong>Fixed the same security issue on three more paths.<\/strong> 1.6.0 closed the REST route, and that was not enough: passport data leaves the site through five doors, and only one of them had been checked. The admin-ajax endpoint was the wide one, because it is guarded by a single site-wide nonce that every anonymous visitor of any passport page receives; with it, any product ID could be requested, drafts included. The three shortcodes accepted a <code>product_id<\/code> attribute without a check, and the free add-on served the same data as a printable page. All five now ask one shared guard (<code>Utils\\Access<\/code>), so the next door cannot be forgotten. A nonce answers whether a request came from our page, never whether the visitor may see the data.<\/li>\n<\/ul>\n\n<h4>1.6.1<\/h4>\n\n<ul>\n<li>Changed: the CSS custom properties in the stylesheet still carried the short <code>--dpp-<\/code> prefix; the rename in 1.6.0 was anchored on quotes and dots, and a custom property is preceded by a hyphen, so no rule matched it. They are now <code>--dppass-<\/code>, in step with the free add-on, which reads two of them.<\/li>\n<li>Fixed: the add-on described its custom CSS field as automatically scoped to a wrapper class that the plugin does not render. The CSS is inserted as written; the help text now says so and names the classes that actually exist.<\/li>\n<\/ul>\n\n<h4>1.6.0<\/h4>\n\n<ul>\n<li><strong>Fixed a security issue: unpublished products could be read through the REST API.<\/strong> The passport route checked the post status, but it read its cache <em>before<\/em> that check and filled it <em>after<\/em>. So an editor opening a draft passport put the draft into the shared cache, and every anonymous request afterwards was answered from that cache without ever reaching the check. Measured on WordPress 7.1: a draft product was handed out in full, manufacturer and GTIN included, status 200. Authorisation now runs first, an unpublished passport is never written to the shared cache, and its response carries <code>Cache-Control: private, no-store<\/code> so no proxy in between can hand it on either.<\/li>\n<li><strong>Fixed: the QR symbol was printed without filtering.<\/strong> The markup is generated inside the plugin, but <code>generate()<\/code> may also return it from a file in <code>wp-content\/uploads<\/code> \u2014 anything able to write there could have put arbitrary markup on the page. Both output paths now run through <code>wp_kses()<\/code> against an allowlist of the five elements a QR symbol consists of. Verified that the generated symbol passes through byte-identical and that script, event handlers, <code>foreignObject<\/code>, <code>use<\/code> and links are removed.<\/li>\n<li><strong>Changed: every option, meta key, hook and handle moved from the <code>dpp_<\/code> prefix to <code>dppass_<\/code>.<\/strong> WordPress.org discards any prefix shorter than four characters. Existing installations are migrated automatically on the first page load after the update \u2014 options, the material library, the supplier list and all 29 passport fields per product. The migration runs on <code>plugins_loaded<\/code>, not on activation, because a plugin update does not activate anything. Nothing has to be re-entered.<\/li>\n<li>Changed: the Pro add-on moves with it. The two share five meta keys, two options, three hooks and one nonce \u2014 <strong>please update both together<\/strong>, otherwise the add-on writes under the old names and the free plugin reads under the new ones.<\/li>\n<li>Fixed: the two global helper functions were still declared as <code>dpp_is_pro()<\/code> and <code>dpp_upgrade_url()<\/code> while their <code>function_exists()<\/code> guards already asked for the new names \u2014 so the guards could never match.<\/li>\n<li>Fixed: the support section linked to a repository that does not exist.<\/li>\n<li>Added: the three public REST routes now document why they carry no authentication gate, and what limits what they hand out.<\/li>\n<li>Fixed: deleting the plugin left data behind. Only three of the seven options were removed, so the material library, the supplier list, the company profile and the add-on settings stayed in the database. The QR cache directory survived too, because the routine that emptied it skipped dot files and then failed to remove a folder that was not empty \u2014 with a PHP warning.<\/li>\n<li>Fixed: uninstalling now also removes data written under the old prefix, for anyone who deletes the plugin before the migration has had a chance to run.<\/li>\n<\/ul>\n\n<h4>1.5.6<\/h4>\n\n<ul>\n<li><strong>QR codes are now generated inside the plugin.<\/strong> Until 1.5.5 every symbol was fetched from api.qrserver.com \u2014 an external request that was never declared, that sent the address of each passport to a third party, and that left the feature dead whenever the service did not answer (the fallback was a grey box, not a scannable code). The encoder now runs locally: no network call, no API key, no third party. Verified by decoding the generated symbols with an independent QR reader.<\/li>\n<li>Fixed: the description called the plugin \"the complete solution\"; it now says what it does.<\/li>\n<li>Fixed: the readme still described the add-on as a \"Pro Version\" that \"unlocks\" features. It has been free since 0.11, and nothing in this plugin is locked \u2014 the wording now matches the admin screens, which have said \"free add-on\" since 1.5.4.<\/li>\n<\/ul>\n\n<h4>1.5.5<\/h4>\n\n<ul>\n<li>Fixed: structured data. WooCommerce already prints a schema.org Product node on the product page; the plugin printed a second one with the passport fields, so search engines saw two products per page. The passport data (manufacturer, country of origin, GTIN, dpp: blocks) now merges into WooCommerce's own Product node via the woocommerce_structured_data_product filter, and the dpp\/un namespaces join the context. Measured: two Product nodes before, one after.<\/li>\n<\/ul>\n\n<h4>1.5.4<\/h4>\n\n<ul>\n<li>Removed: every artificial limit in the free plugin. Custom materials were capped at 10 and suppliers at a fixed number, product fields could be marked \"Pro only\", and a 30-day notice plus several \"Upgrade\" links pointed at an add-on page \u2014 while the code to lift each limit sat in this very plugin. WordPress.org guideline 5\/6 forbids exactly that, and the add-on being free does not change it. The free plugin is now complete for what it does; the add-on adds separate features (analytics, PDF, bulk import\/export, compliance checker, e-mail, WPML).<\/li>\n<li>Removed: a \"Download PDF (Pro)\" link shown to <em>shop visitors<\/em> that pointed into wp-admin.<\/li>\n<li>Removed: the last Freemius branch in <code>dpp_upgrade_url()<\/code>.<\/li>\n<li>Added: the plugin registers with the AOS Hub and shows a footer line on its own admin screens only.<\/li>\n<\/ul>\n\n<h4>1.5.3<\/h4>\n\n<ul>\n<li>Changed: the text domain is now <code>digital-product-passport-for-woocommerce<\/code>, matching the\nplugin name. WordPress.org derives a plugin's permalink from the plugin name, and language\npacks are looked up by text domain \u2014 with the two out of step, no translation would ever\nhave loaded. Nothing users store changes: every option, hook and meta key keeps its <code>dpp_<\/code>\nprefix.<\/li>\n<li>Removed: the runtime .po \u2192 .mo compiler. It wrote into the plugin's own directory, which is\noverwritten on every update and is not writable on many hosts \u2014 and it could never do\nanything in a released package anyway, because .po files are not shipped (WordPress.org\nbuilds translations itself). With it went the <code>load_plugin_textdomain()<\/code> call it required;\nWordPress has loaded language packs on its own since 4.6.<\/li>\n<li>Fixed: prefixed the seven plugin constants (<code>DPP_<\/code> \u2192 <code>DPPASS_<\/code>). Plugin Check discards any\nprefix shorter than four characters, so all seven were reported as unprefixed globals.<\/li>\n<li>Fixed: <code>fgetcsv()<\/code>\/<code>fputcsv()<\/code> now pass <code>$escape<\/code> explicitly. PHP 8.4 deprecates the implicit\ndefault, and the plugin declares PHP 8.0, which includes 8.4.<\/li>\n<li>Fixed: the QR cache protection files are written through <code>WP_Filesystem<\/code>. On installations\nthat write over FTP the previous direct write silently did nothing \u2014 and that is exactly\nwhere the directory would have been left unprotected.<\/li>\n<\/ul>\n\n<h4>1.5.2<\/h4>\n\n<ul>\n<li><strong>The \"Powered by\" badge is off by default.<\/strong> Until now it appeared on every passport unless the site owner bought the Pro add-on to switch it off. A credit on the visitor-facing page has to be opt-in \u2014 that is plugin guideline 11, and gating the off-switch behind a paid upgrade made it worse. The setting is still there under Settings \u2192 General; it simply starts switched off.<\/li>\n<\/ul>\n\n<h4>1.5.1<\/h4>\n\n<ul>\n<li>Fixed: every request to \/dpp\/v1\/passport\/{id} ended in a fatal error on PHP 8. The route used bare 'is_numeric' as its validate_callback; WordPress calls that with three arguments and PHP-internal functions reject the surplus.<\/li>\n<li>Security: the passport route served unpublished products. A draft was handed out in full \u2014 name, permalink, manufacturer \u2014 to anyone walking the IDs. Only published products are public now; users who may edit the product still get it, so previewing from the admin keeps working.<\/li>\n<li>Fixed: six links in the plugin and the readme pointed at pages that do not exist (\/docs\/\u2026 and \/plugins\/\u2026). They now point at the product page.<\/li>\n<li>Added: \"Requires Plugins\" header, so WordPress blocks activation without WooCommerce and offers to install it.<\/li>\n<\/ul>\n\n<h4>1.5.0<\/h4>\n\n<ul>\n<li>Fix: Fatal error when re-activating the Pro plugin after deactivation (undefined constant <code>DPP_PRO_VERSION<\/code> at activation time \u2014 now uses <code>DPP_PRO_VERSION_RAW<\/code>)<\/li>\n<li>Fix: Replaced direct PHP <code>is_writable()<\/code> with <code>wp_is_writable()<\/code> in the MO generator for full WP Filesystem API compliance<\/li>\n<li>Fix: Added missing translators comment for the material library counter string<\/li>\n<li>Fix: Supplier manager <code>$_POST<\/code> access now fully phpcs-annotated for WordPress.Security compliance<\/li>\n<li>Fix: <code>uninstall.php<\/code> global variable names annotated for Plugin Check compliance<\/li>\n<li>Fix: <code>load_plugin_textdomain()<\/code> phpcs-annotated (kept intentionally for MO auto-compilation fallback)<\/li>\n<li>Code: All Plugin Check ERRORs and WARNINGs resolved to pass WP.org automated review<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>New: Bulk editor expanded with Brand, Serial No., CO\u2082 Methodology, and Durability columns<\/li>\n<li>New: Supplier modal rebuilt as sticky flex layout (header\/body\/footer scroll independently)<\/li>\n<li>New: Apply Template always overwrites existing values with a yellow-flash confirmation<\/li>\n<li>New: QR code block spans full width in multi-column frontend layouts<\/li>\n<li>Fix: Analytics chart now loads reliably via <code>wp_add_inline_script<\/code> (timing fix)<\/li>\n<li>Fix: jsDelivr CDN fallback for Chart.js when local file is missing<\/li>\n<li>Fix: Import\/Export button dashicons aligned correctly on all screen sizes<\/li>\n<li>Fix: Custom CSS &amp; Branding Pro feature card added to upgrade page<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>New: Full ESPR \/ EU 2024\/1781 field set \u2014 brand name, manufacturer address, CO\u2082 methodology, substances of concern, repairability index, spare parts, durability, compliance fields<\/li>\n<li>New: GS1 Digital Link QR code URLs (<code>\/01\/{gtin}\/21\/{serial}<\/code>)<\/li>\n<li>New: QR codes switched from deprecated Google Charts API to qrserver.com (reliable SVG, locally cached)<\/li>\n<li>New: Completeness score progress bar in product panel<\/li>\n<li>New: Display position setting \u2014 modal button or inline product tab<\/li>\n<li>New: Repairability section in frontend passport display<\/li>\n<li>New: ESPR compliance footer badge in passport<\/li>\n<li>New: <code>dpp_passport_viewed<\/code> and <code>dpp_passport_content_end<\/code> action hooks for Pro extensions<\/li>\n<li>New: CSS custom properties for easy theme integration<\/li>\n<li>New: ARIA focus trap and keyboard navigation in passport modal<\/li>\n<li>New: Cart and Checkout Blocks compatibility declaration<\/li>\n<li>New: Dismissible admin upgrade notice<\/li>\n<li>Improved: Admin panel UI \u2014 section icons, locked Pro fields, panel-level CTA<\/li>\n<li>Improved: Material rows now include a recycled content % column<\/li>\n<li>Improved: Settings page redesigned with Upgrade page feature cards<\/li>\n<li>Improved: REST API adds transient caching and rate limiting<\/li>\n<li>Improved: JSON-LD output extended with all new ESPR fields and W3ID DPP ontology<\/li>\n<li>Improved: Frontend CSS fully redesigned with mobile bottom-sheet animation<\/li>\n<li>Requires: WordPress 6.4+, WooCommerce 8.0+, PHP 8.0+<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release<\/li>\n<li>ESPR compliance fields<\/li>\n<li>QR code generation<\/li>\n<li>REST API<\/li>\n<li>WooCommerce product tab integration<\/li>\n<\/ul>","raw_excerpt":"Create ESPR-compliant Digital Product Passports for your WooCommerce products with QR codes, structured data, and a REST API.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/366019","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=366019"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/aosdigital"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=366019"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=366019"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=366019"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=366019"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=366019"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=366019"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}