{"id":333697,"date":"2026-07-15T13:26:17","date_gmt":"2026-07-15T13:26:17","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/toko-toolkit-for-ecommerce-invoices-email-compliance-more\/"},"modified":"2026-07-28T11:19:37","modified_gmt":"2026-07-28T11:19:37","slug":"kramar","status":"publish","type":"plugin","link":"https:\/\/nl.wordpress.org\/plugins\/kramar\/","author":18529643,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.1","stable_tag":"1.0.1","tested":"7.0.2","requires":"7.0","requires_php":"8.4","requires_plugins":null,"header_name":"Kramar - Toolkit for eCommerce: Invoices, Email, Compliance & More","header_author":"Naiche","header_description":"EU\/NL compliance, PDF invoices, a drag-and-drop email builder, checkout field editor, custom order statuses, product & performance tools \u2014 27 modules in one lean plugin for WooCommerce.","assets_banners_color":"182054","last_updated":"2026-07-28 11:19:37","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wordpress.org\/plugins\/kramar\/","header_author_uri":"https:\/\/profiles.wordpress.org\/naiches\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":96,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"naiches","date":"2026-07-15 13:25:56"},"1.0.1":{"tag":"1.0.1","author":"naiches","date":"2026-07-28 11:19:37"}},"upgrade_notice":{"1.0.1":"<p>Fixes duplicate customer emails on custom order statuses, order statuses that silently reverted to Pending, and a withdrawal verification email that ignored its own settings.<\/p>","1.0.0":"<p>Initial release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3608942,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3608942,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.jpg":{"filename":"banner-1544x500.jpg","revision":3610290,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.jpg":{"filename":"banner-772x250.jpg","revision":3610290,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0","1.0.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3608942,"resolution":"1","location":"assets","locale":"","width":1440,"height":900},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3608942,"resolution":"2","location":"assets","locale":"","width":1440,"height":900},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3608942,"resolution":"3","location":"assets","locale":"","width":1440,"height":900},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3608942,"resolution":"4","location":"assets","locale":"","width":1440,"height":900},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3608942,"resolution":"5","location":"assets","locale":"","width":1440,"height":900}},"screenshots":{"1":"Dashboard \u2014 get-started checklist, module\/compliance stat cards, and an action-required panel.","2":"Modules \u2014 enable only what you need; every module is opt-in and grouped by area.","3":"Invoice template builder \u2014 drag-and-drop blocks with a live, true-to-print PDF preview.","4":"Email Manager \u2014 toggle WooCommerce emails, edit each one, or add your own custom transactional emails.","5":"Checkout field editor \u2014 add, reorder, and edit billing, shipping, and additional checkout fields."}},"plugin_section":[],"plugin_tags":[15962,155593,131785,16236,130912],"plugin_category":[],"plugin_contributors":[195720],"plugin_business_model":[],"class_list":["post-333697","plugin","type-plugin","status-publish","hentry","plugin_tags-abandoned-cart","plugin_tags-back-in-stock","plugin_tags-gdpr","plugin_tags-invoices","plugin_tags-variation-swatches","plugin_contributors-naiches","plugin_committers-naiches"],"banners":{"banner":"https:\/\/ps.w.org\/kramar\/assets\/banner-772x250.jpg?rev=3610290","banner_2x":"https:\/\/ps.w.org\/kramar\/assets\/banner-1544x500.jpg?rev=3610290","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/kramar\/assets\/icon-128x128.png?rev=3608942","icon_2x":"https:\/\/ps.w.org\/kramar\/assets\/icon-256x256.png?rev=3608942","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/kramar\/assets\/screenshot-1.png?rev=3608942","caption":"Dashboard \u2014 get-started checklist, module\/compliance stat cards, and an action-required panel."},{"src":"https:\/\/ps.w.org\/kramar\/assets\/screenshot-2.png?rev=3608942","caption":"Modules \u2014 enable only what you need; every module is opt-in and grouped by area."},{"src":"https:\/\/ps.w.org\/kramar\/assets\/screenshot-3.png?rev=3608942","caption":"Invoice template builder \u2014 drag-and-drop blocks with a live, true-to-print PDF preview."},{"src":"https:\/\/ps.w.org\/kramar\/assets\/screenshot-4.png?rev=3608942","caption":"Email Manager \u2014 toggle WooCommerce emails, edit each one, or add your own custom transactional emails."},{"src":"https:\/\/ps.w.org\/kramar\/assets\/screenshot-5.png?rev=3608942","caption":"Checkout field editor \u2014 add, reorder, and edit billing, shipping, and additional checkout fields."}],"raw_content":"<!--section=description-->\n<p>Kramar is a modular WooCommerce toolkit built for EU compliance and performance. Instead of installing a dozen separate single-purpose plugins, Kramar provides a focused set of tools in one clean package \u2014 27 modules across ten areas. Every module is opt-in and disabled by default, so you only run what you actually use.<\/p>\n\n<p><strong>About the name:<\/strong> <em>Kramar<\/em> (\u043a\u0440\u0430\u043c\u0430\u0440) is an old Ukrainian word for a <em>merchant<\/em> \u2014 the town shopkeeper who dealt in wares. Its root, <em>kram<\/em> (goods), is a medieval German trade-loanword that travelled east into the Slavic languages, a small echo of Europe's old merchant network. Kramar is the toolkit that equips the merchant.<\/p>\n\n<h4>What's included<\/h4>\n\n<ul>\n<li><strong>EU &amp; NL compliance<\/strong> \u2014 Legal consent checkboxes, EU payment-obligation order-button text (Dutch Hoge Raad ruling), Omnibus 30-day lowest-price display, unit-price \/ delivery-time \/ tax notices, and a 14-day right-of-withdrawal \/ return flow.<\/li>\n<li><strong>PDF documents<\/strong> \u2014 Article 226-compliant invoices, packing slips, and credit notes, with sequential numbering and encrypted storage.<\/li>\n<li><strong>Email<\/strong> \u2014 A drag-and-drop email template builder, custom transactional emails with status \/ time-delay \/ manual triggers, and a developer API.<\/li>\n<li><strong>Checkout<\/strong> \u2014 A checkout field editor (classic + block checkout), address validation, EU VAT ID format validation for B2B orders, and a delivery-date picker.<\/li>\n<li><strong>Order management<\/strong> \u2014 Custom order statuses, sequential order numbers, and a refund \/ return workflow.<\/li>\n<li><strong>Products<\/strong> \u2014 Variation swatches (colour or image), minimum \/ maximum \/ step quantity rules, extra product option fields, and enhanced reviews (verified-buyer badge, helpful voting, rating breakdown).<\/li>\n<li><strong>Marketing<\/strong> \u2014 Google Shopping product feed, back-in-stock notifications, abandoned-cart recovery, and post-purchase review reminders \u2014 all consent-first.<\/li>\n<li><strong>Customer account<\/strong> \u2014 An enhanced My Account dashboard with order tracking, one-click reorder, and a smoother registration flow.<\/li>\n<li><strong>Shipping<\/strong> \u2014 Weight-based shipping rates.<\/li>\n<li><strong>Performance<\/strong> \u2014 Disable cart-fragment polling, dequeue unused WooCommerce CSS\/JS, and strip WooCommerce admin bloat.<\/li>\n<li><strong>Privacy<\/strong> \u2014 Order and review IP anonymisation, data-retention warnings, and scheduled PII cleanup.<\/li>\n<\/ul>\n\n<h4>Built for the EU<\/h4>\n\n<p>Kramar was designed from the ground up for EU and Dutch law. The compliance modules consider the GDPR, the Consumer Rights Directive, the Omnibus Directive, and Dutch civil-code requirements. They are entirely optional \u2014 the invoicing, email, product, performance, and order tools work for any store, anywhere.<\/p>\n\n<h4>Modular<\/h4>\n\n<p>Enable only what you need. Disabled modules have zero overhead \u2014 no hooks, no queries, no assets loaded.<\/p>\n\n<h3>For Developers<\/h3>\n\n<p>Kramar's Email Manager module exposes a small PHP API for sending and scheduling custom emails from themes or other plugins. No code is needed to <em>create<\/em> a custom email \u2014 use Kramar \u2192 Emails \u2192 Add New Email in the admin to build and configure it. Once it exists you can trigger it programmatically.<\/p>\n\n<h4>Finding a custom email's id<\/h4>\n\n<p>Every custom email created through the UI gets an id of the form <code>kramar_custom_{slug}<\/code>, where the slug is derived from the email name: spaces become underscores, all characters are lowercased, and the result is passed through <code>sanitize_key()<\/code>. Example: an email named \"Review Request\" becomes <code>kramar_custom_review_request<\/code>. The exact id is shown in the Custom Emails table on Kramar \u2192 Emails.<\/p>\n\n<h4>Sending immediately<\/h4>\n\n<pre><code>kramar_send_email( string $id, mixed $context = null ): bool\n<\/code><\/pre>\n\n<p>Sends the custom email right now. Returns <code>true<\/code> if the email was dispatched (the email was found, is enabled, and passed the send filters). <code>$context<\/code> may be a <code>WC_Order<\/code> object, an order id (integer or numeric string), or <code>null<\/code>.<\/p>\n\n<pre><code>kramar_send_email( 'kramar_custom_review_request', $order_id );\n<\/code><\/pre>\n\n<h4>Scheduling for later<\/h4>\n\n<pre><code>kramar_schedule_email( string $id, mixed $context, int $timestamp ): bool\n<\/code><\/pre>\n\n<p>Schedules the email via Action Scheduler at the given Unix timestamp. Returns <code>true<\/code> if the action was queued (or was already queued). Requires WooCommerce's bundled Action Scheduler.<\/p>\n\n<pre><code>kramar_schedule_email( 'kramar_custom_review_request', $order_id, time() + 7 * DAY_IN_SECONDS );\n<\/code><\/pre>\n\n<h4>Idiomatic do_action aliases<\/h4>\n\n<p>Both functions are also wired to <code>do_action<\/code> so callers that prefer hooks over direct function calls can use:<\/p>\n\n<pre><code>do_action( 'kramar_send_email', $id, $context );\ndo_action( 'kramar_schedule_email', $id, $context, $timestamp );\n<\/code><\/pre>\n\n<h4>Filters<\/h4>\n\n<p><strong><code>kramar_email_recipient<\/code><\/strong> \u2014 Override the To address before the email is sent.<\/p>\n\n<pre><code>apply_filters( 'kramar_email_recipient', string $recipient, string $id, WC_Order|null $order )\n<\/code><\/pre>\n\n<p><strong><code>kramar_email_should_send<\/code><\/strong> \u2014 Return <code>false<\/code> to prevent a send entirely.<\/p>\n\n<pre><code>apply_filters( 'kramar_email_should_send', bool $should, string $id, WC_Order|null $order )\n<\/code><\/pre>\n\n<p><strong><code>kramar_email_merge_field_values<\/code><\/strong> \u2014 Add or replace merge-field values used inside email content.<\/p>\n\n<pre><code>apply_filters( 'kramar_email_merge_field_values', array $replacements, WC_Order $order )\n<\/code><\/pre>\n\n<h4>Worked example: review request 7 days after order completion<\/h4>\n\n<pre><code>add_action( 'woocommerce_order_status_completed', function ( $order_id ) {\n    kramar_schedule_email( 'kramar_custom_review_request', $order_id, time() + 7 * DAY_IN_SECONDS );\n} );\n<\/code><\/pre>\n\n<p><strong>Note:<\/strong> The WooCommerce mailer caches its email list per request. A custom email created in the same PHP request as your <code>kramar_send_email()<\/code> call will not yet be registered and the call will return <code>false<\/code>. In normal use \u2014 emails created in the admin, triggered later by frontend or cron events \u2014 this is never a concern.<\/p>\n\n<h4>Delivery time (template tag)<\/h4>\n\n<p>Display a product's delivery-time estimate anywhere in your theme:<\/p>\n\n<pre><code>kramar_get_delivery_time( int $product_id = 0 ): string\n<\/code><\/pre>\n\n<p>Returns the product's own delivery-time term, falling back to the shop-wide default set in the EU Product Compliance module (or an empty string when neither is set). Works even when the automatic front-end display is turned off. Pass <code>0<\/code> to use the current global <code>$product<\/code>.<\/p>\n\n<pre><code>echo esc_html( kramar_get_delivery_time( $product-&gt;get_id() ) );\n<\/code><\/pre>\n\n<p><strong><code>kramar_delivery_time_label<\/code><\/strong> \u2014 Filter the resolved label.<\/p>\n\n<pre><code>apply_filters( 'kramar_delivery_time_label', string $label, int $product_id )\n<\/code><\/pre>\n\n<p><strong><code>kramar_delivery_time_html<\/code><\/strong> \u2014 Filter the rendered <code>&lt;span class=\"kramar-delivery-time\"&gt;<\/code> markup (escape your own output).<\/p>\n\n<pre><code>apply_filters( 'kramar_delivery_time_html', string $html, string $label, WC_Product $product )\n<\/code><\/pre>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate WooCommerce (required).<\/li>\n<li>Upload the <code>kramar<\/code> folder to <code>\/wp-content\/plugins\/<\/code>, or install it from the Plugins screen.<\/li>\n<li>Activate the plugin.<\/li>\n<li>Open the <strong>Kramar<\/strong> menu in your admin sidebar and enable the modules you want.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20kramar%20require%20woocommerce%3F\"><h3>Does Kramar require WooCommerce?<\/h3><\/dt>\n<dd><p>Yes. WooCommerce must be installed and active \u2014 Kramar declares it as a required plugin and will not run without it.<\/p><\/dd>\n<dt id=\"do%20i%20have%20to%20use%20every%20module%3F\"><h3>Do I have to use every module?<\/h3><\/dt>\n<dd><p>No. Every module is opt-in and disabled by default. A disabled module registers no hooks, runs no queries, and loads no assets.<\/p><\/dd>\n<dt id=\"are%20the%20pdf%20invoices%20legally%20compliant%3F\"><h3>Are the PDF invoices legally compliant?<\/h3><\/dt>\n<dd><p>Invoices include the fields required by Article 226 of the EU VAT Directive and use gap-free sequential numbering. Please confirm the output meets your obligations with your own accountant, as requirements vary by country and business type.<\/p><\/dd>\n<dt id=\"where%20are%20generated%20pdfs%20stored%3F\"><h3>Where are generated PDFs stored?<\/h3><\/dt>\n<dd><p>They are stored encrypted inside your site's uploads directory and are served only through authenticated, capability-checked download endpoints \u2014 never from a public URL.<\/p><\/dd>\n<dt id=\"can%20i%20use%20kramar%20outside%20the%20eu%3F\"><h3>Can I use Kramar outside the EU?<\/h3><\/dt>\n<dd><p>Yes. The compliance modules are optional. The invoicing, email, product, performance, and order-management tools work for any WooCommerce store.<\/p><\/dd>\n<dt id=\"can%20i%20send%20a%20custom%20email%20from%20my%20own%20code%3F\"><h3>Can I send a custom email from my own code?<\/h3><\/dt>\n<dd><p>Yes. Create the email in <strong>Kramar \u2192 Emails \u2192 Add New Email<\/strong>, then trigger it programmatically with <code>kramar_send_email()<\/code> or <code>kramar_schedule_email()<\/code>. See the \"For Developers\" section below.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Fixed: custom order status notifications were sent to the customer twice. The status module sent its own copy alongside the one delivered by the Email Manager; only the Email Manager copy is sent now, so From name, BCC and the email template all apply correctly.<\/li>\n<li>Fixed: a custom order status whose slug was longer than 17 characters could not be applied to an order \u2014 on databases without strict mode the status was silently truncated and the order fell back to Pending, with no error anywhere. Slug length is now validated when the status is saved, and any existing over-long status is flagged on the Order Statuses screen.<\/li>\n<li>Added: custom order statuses now have their own Slug field, so a long, readable status name (for example \"Binnen 5 werkdagen\") can be paired with a short slug. Leave it blank to generate one from the name.<\/li>\n<li>Fixed: clearing \"Sends email\" on a custom order status now stops its notification instead of leaving it active.<\/li>\n<li>Fixed: renaming a custom order status left its auto-generated notification email showing the old status name in its title, subject, and heading, with no way to correct it. Renaming a status now updates the email's name, subject, and description to match (any custom subject set in the Email Builder is preserved).<\/li>\n<li>Added: the legal checkbox settings now warn when an enabled checkbox uses a {..._link} placeholder with no page selected \u2014 the placeholder would otherwise render as plain, unclickable text at checkout.<\/li>\n<li>Fixed: the withdrawal verification email ignored its own on\/off switch on the Emails screen and kept sending, ignored the subject set in the Email Builder, and was delivered without the configured Reply-To, CC or BCC. It is now sent the same way as every other Kramar email.<\/li>\n<li>Fixed: the default withdrawal verification template rendered its two body paragraphs as empty text and its button pointed at a dead link, so customers received a bare button they could not use. Existing templates are repaired automatically.<\/li>\n<li>Fixed: creating a custom email with a name that differed only in capitalisation or punctuation from an existing one silently replaced it, leaving the old template attached to the new email. The name is now rejected with an explanation, and errors from this dialog are shown instead of being swallowed.<\/li>\n<li>Fixed: custom order status slugs can no longer collide with the statuses used by the Refund &amp; Returns module.<\/li>\n<li>Fixed: deleting a custom order status left its notification email active in the Email Manager.<\/li>\n<li>Fixed: the guest order-tracking email was sent without a From or Reply-To address, so it came from WordPress rather than the shop and was liable to be rejected or filtered as spam.<\/li>\n<li>Fixed (Dutch): the default privacy consent label used the wrong article (\"Ik heb het \u2026\" instead of \"Ik heb de \u2026\"). Note that this label is stored in your settings the first time it is saved, so an existing site needs the wording corrected under Kramar &rarr; Modules &rarr; Legal Checkboxes.<\/li>\n<li>Fixed: saving Business Details or the Email Sender defaults on the Settings page silently failed (returned \"0\") when the Email Manager module was disabled. Their save handlers are now registered independently of the module's enabled state.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"PDF invoices, email builder, EU\/NL compliance, checkout editor, custom order statuses &amp; more \u2014 one modular toolkit for WooCommerce.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/333697","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=333697"}],"author":[{"embeddable":true,"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/naiches"}],"wp:attachment":[{"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=333697"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=333697"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=333697"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=333697"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=333697"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/nl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=333697"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}