{"id":359893,"date":"2026-08-30T15:22:17","date_gmt":"2026-08-30T15:22:17","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/mhm-currency-switcher\/"},"modified":"2026-08-30T15:21:55","modified_gmt":"2026-08-30T15:21:55","slug":"mhm-currency-switcher","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/mhm-currency-switcher\/","author":20854694,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"2.1.0","stable_tag":"2.1.0","tested":"7.1","requires":"6.6","requires_php":"7.4","requires_plugins":null,"header_name":"MHM Currency Switcher","header_author":"MaxHandMade","header_description":"Multi-currency support for WooCommerce with real-time exchange rates and seamless checkout integration.","assets_banners_color":"5582a4","last_updated":"2026-08-30 15:21:55","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wpalemi.com\/currency-switcher\/","header_author_uri":"https:\/\/wpalemi.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":60,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"2.1.0":{"tag":"2.1.0","author":"maxhandmade","date":"2026-08-30 15:21:55","revision":3672767}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3672756,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3672756,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3672756,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3672756,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["2.1.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3672756,"resolution":"1","location":"assets","locale":"","width":690,"height":544},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3672756,"resolution":"2","location":"assets","locale":"","width":610,"height":278},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3672756,"resolution":"3","location":"assets","locale":"","width":1200,"height":750},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3672756,"resolution":"4","location":"assets","locale":"","width":1200,"height":860},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3672756,"resolution":"5","location":"assets","locale":"","width":1200,"height":1147},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3672756,"resolution":"6","location":"assets","locale":"","width":1200,"height":1556}},"screenshots":{"1":"A shop priced in US dollars, as a visitor sees it after choosing Turkish\nlira. The page itself was served in the shop's base currency; the prices\nwere converted afterwards.","2":"The switcher added to a site's navigation menu, with its list open.","3":"Manage Currencies \u2014 each currency has its own rate, fee and rounding rules,\nand every row shows the converted price a customer would see.","4":"Display Options \u2014 a live preview of the switcher, what it shows, how large\nit is, and whether product pages carry a multi-currency price list.","5":"Advanced \u2014 geolocation, the automatic rate-update interval, cache\ncompatibility mode, and whether removing the plugin deletes its data.","6":"How to use \u2014 every way the switcher can be placed, including the navigation\nmenu item, with copyable code and the price-list shortcode's attributes."}},"plugin_section":[],"plugin_tags":[8504,21294,16558,24514,286],"plugin_category":[45],"plugin_contributors":[277101],"plugin_business_model":[],"class_list":["post-359893","plugin","type-plugin","status-publish","hentry","plugin_tags-currency","plugin_tags-currency-switcher","plugin_tags-exchange-rate","plugin_tags-multi-currency","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-maxhandmade","plugin_committers-maxhandmade"],"banners":{"banner":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/banner-772x250.png?rev=3672756","banner_2x":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/banner-1544x500.png?rev=3672756","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/icon-128x128.png?rev=3672756","icon_2x":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/icon-256x256.png?rev=3672756","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/screenshot-1.png?rev=3672756","caption":"A shop priced in US dollars, as a visitor sees it after choosing Turkish\nlira. The page itself was served in the shop's base currency; the prices\nwere converted afterwards."},{"src":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/screenshot-2.png?rev=3672756","caption":"The switcher added to a site's navigation menu, with its list open."},{"src":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/screenshot-3.png?rev=3672756","caption":"Manage Currencies \u2014 each currency has its own rate, fee and rounding rules,\nand every row shows the converted price a customer would see."},{"src":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/screenshot-4.png?rev=3672756","caption":"Display Options \u2014 a live preview of the switcher, what it shows, how large\nit is, and whether product pages carry a multi-currency price list."},{"src":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/screenshot-5.png?rev=3672756","caption":"Advanced \u2014 geolocation, the automatic rate-update interval, cache\ncompatibility mode, and whether removing the plugin deletes its data."},{"src":"https:\/\/ps.w.org\/mhm-currency-switcher\/assets\/screenshot-6.png?rev=3672756","caption":"How to use \u2014 every way the switcher can be placed, including the navigation\nmenu item, with copyable code and the price-list shortcode's attributes."}],"raw_content":"<!--section=description-->\n<p>MHM Currency Switcher adds multi-currency support to your WooCommerce store. Customers can browse products, add items to their cart, and complete checkout in their preferred currency with real-time exchange rates.<\/p>\n\n<p><strong>Key Features<\/strong><\/p>\n\n<ul>\n<li>Add multiple currencies with real-time exchange rates<\/li>\n<li>Cache compatibility mode \u2014 works behind a page cache without serving one visitor's currency to everybody<\/li>\n<li>Currency switcher via shortcode \u2014 usable in a text widget, nav menu, or Elementor<\/li>\n<li>Product page price display widget with country flags<\/li>\n<li>Navigation menu integration \u2014 add switcher to any WordPress menu<\/li>\n<li>Automatic exchange rate fetching (ExchangeRate-API)<\/li>\n<li>Fee &amp; rounding configuration per currency<\/li>\n<li>Cookie-based currency persistence<\/li>\n<li>WooCommerce HPOS compatible<\/li>\n<li>Elementor widgets included<\/li>\n<li>Every currency WooCommerce offers<\/li>\n<li>Scheduled automatic exchange rate updates<\/li>\n<li>Geolocation-based currency detection<\/li>\n<li>Fixed prices per product<\/li>\n<li>\"How to use\" tab in the settings screen, naming every way the switcher can be placed<\/li>\n<\/ul>\n\n<p><strong>Cache compatibility mode<\/strong><\/p>\n\n<p>A page cache stores the HTML your server produced for whoever asked first. When\nprices are converted on the server, that means the first visitor's currency is\nwhat every later visitor is served. Cache compatibility mode, which is on by\ndefault, avoids this: anonymous shop, archive and product pages are rendered in\nyour base currency, so the same cached page is correct for everyone, and the\nbrowser converts the prices it can see afterwards through a REST request to this\nplugin.<\/p>\n\n<p>The split is deliberate. Only <em>displayed<\/em> prices are converted in the browser.\nCart, checkout, order totals, order emails and the WooCommerce REST API are\nalways calculated on the server in the currency the customer actually chose, so\nthe amount charged cannot be altered from the browser.<\/p>\n\n<p>You can switch the mode off under <strong>WooCommerce &gt; MHM Currency &gt;\nAdvanced<\/strong>, in which case prices are converted on the server as they were before\nthis feature existed. Read \"Known limits\" below before deciding either way \u2014\nboth settings have consequences, and they are different ones.<\/p>\n\n<h3>Known limits<\/h3>\n\n<p>These are consequences of how cache compatibility mode works, not defects. They\nare listed so you can decide with your eyes open.<\/p>\n\n<h4>Turning the mode off does not restore the exact 1.0.0 behaviour<\/h4>\n\n<p>Three fixes sit above the setting and stay in place whether it is on or off:\nprices are no longer converted on admin screens or in admin AJAX (which used to\nwrite a converted price into an order line item), <code>wc\/v3<\/code> REST reads are pinned\nto the base currency, and scheduled tasks and WP-CLI no longer convert. Switching\nthe mode off restores the 1.0.0 <em>display<\/em> behaviour \u2014 prices converted on the\nserver \u2014 and nothing else.<\/p>\n\n<h4>Search engines and crawlers see your base prices<\/h4>\n\n<p>With the mode on, the page a crawler fetches has not been through the browser,\nso it carries base-currency prices, and so does the machine-readable product data\nin it. See the structured data question above; the mismatch is deliberate.<\/p>\n\n<h4>Converted prices replace the base ones a moment after the page appears<\/h4>\n\n<p>The page arrives with your base-currency prices already on screen \u2014 nothing is\nhidden waiting for JavaScript \u2014 and the browser swaps in the converted ones as\nsoon as its request comes back, each price fading over 200ms as it changes. On a\nslow connection the base price is readable for longer before the swap. Visitors\nwho have asked their system for reduced motion get the swap without the fade.<\/p>\n\n<h4>With JavaScript disabled, or the endpoint unreachable, base prices stay<\/h4>\n\n<p>Nothing breaks and no error is shown to the visitor \u2014 the page simply keeps the\nbase-currency prices it was rendered with, and the reason is written to the\nbrowser console. Cart and checkout are unaffected, because they never depended\non the browser in the first place.<\/p>\n\n<h4>Variable products make one extra request, and some swatch plugins lose the price<\/h4>\n\n<p>On a cacheable page the plugin forces WooCommerce to fetch variation prices over\nAJAX, because the variations JSON WooCommerce would otherwise embed in the page\ncarries base-currency prices that its own scripts write straight into the page.\nThe cost is one request when a visitor picks a variation, and that\n    data-product_variations is <code>false<\/code>: third-party colour or size swatch plugins\nthat read prices out of that JSON instead of asking WooCommerce may stop showing\na price. If you use such a plugin, check a variable product before going live.<\/p>\n\n<h4>The mini-cart relies on WooCommerce cart fragments<\/h4>\n\n<p>A mini-cart is rendered on every page, so it cannot be classified per request.\nIt is rendered in the base currency and then corrected by WooCommerce's own cart\nfragment refresh, which is a server-side conversion. If cart fragments are\ndisabled on your site \u2014 some themes and optimisation plugins dequeue them \u2014 the\ncached mini-cart total stays in the base currency while the rest of the page\nconverts. The plugin watches for this and says so in the admin when it happens;\na site with no mini-cart at all is never warned about it.<\/p>\n\n<h4>A cart or checkout on a page WooCommerce does not know about must be excluded from your cache<\/h4>\n\n<p>Page caches exclude cart and checkout automatically because they recognise the\npages WooCommerce assigned. If you have put a cart or checkout shortcode or block\non some other page, exclude that page yourself. Two things go wrong otherwise:\nthe conversion decision flips to \"convert\" partway through the render, so the\nrest of the page is printed already converted and without the markers the browser\nlooks for, and blocks-based cart and checkout embed their amounts in the page as\nJSON while rendering. Either way the first visitor's currency is what the cache\nthen hands to everyone. Cart contents are personal anyway; such a page should not\nbe cached.<\/p>\n\n<h4>`?currency=` multiplies your cache entries<\/h4>\n\n<p>A currency can be requested in the URL, and a cache treats every distinct URL as\na separate entry, so linking to <code>?currency=EUR<\/code> and <code>?currency=GBP<\/code> stores the\nsame page more than once. The switcher itself does not produce these URLs \u2014 it\nwrites a cookie and leaves the address alone. On a cached page it converts the\nprices where they stand; on the cart page, for a logged-in visitor, or with\ncache compatibility switched off, it reloads instead. Either way the URL is the\none the visitor was already on, so no extra cache entry is created.<\/p>\n\n<p>A <code>?currency=<\/code> link also applies to that page view only: it deliberately sets no\ncookie, so the next page the visitor opens is back in your base currency unless\nthey use the switcher. That is not an oversight \u2014 a link that silently pinned a\ncurrency could show one currency in the catalogue while the cart, which reads\nthe cookie, charged another. If you want a campaign link that sticks, send\nvisitors to a page carrying the switcher rather than relying on the parameter.<\/p>\n\n<h4>WooCommerce Analytics adds different currencies together<\/h4>\n\n<p>An order is stored in the currency the customer paid in, and WooCommerce\nAnalytics reports every order's figures in your store currency without\nconverting them back. A 4.38 USD order is counted as 4.38 in your base\ncurrency, so once you take orders in more than one currency the revenue\nfigures in Analytics, and the totals in the customer panel on the order\nscreen, are sums of unlike amounts. The orders themselves are correct \u2014 each\none keeps its own currency, total and the exchange rate it was placed at, and\nthis plugin stores that rate on the order. It is the aggregate reports that\ncannot be read as money. Nothing in this plugin can fix that from the outside;\nif you need accurate multi-currency reporting, export the orders and convert\nthem using the rate recorded on each one.<\/p>\n\n<h4>Logged-in visitors are converted on the server<\/h4>\n\n<p>Logged-in visitors take the server-side path, which is correct as long as your\ncache does what nearly all of them do and never serves cached pages to logged-in\nusers. An edge cache or CDN configured to cache without looking at cookies is the\nexception, and there a logged-in visitor's converted page can be stored and\nserved on. If you cache at the edge, confirm it varies on the login cookie.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin connects to two third-party services to keep currency conversion\nrates up to date. What each one is sent, and when, is described separately\nbelow because the two are not the same. Both requests are made with PHP's\n    WP_Http transport, which in WordPress's default configuration sends a\n    User-Agent header of the form <code>WordPress\/{version}; {your site's URL}<\/code> --\nso the site's own address leaves with every request to either service, not\njust the data described below. That header is filterable\n(<code>http_headers_useragent<\/code>, <code>http_request_args<\/code>), so a site that has changed\nit will send something different.<\/p>\n\n<p><strong>ExchangeRate-API<\/strong><\/p>\n\n<p>What it is: a commercial exchange-rate API, used as the primary source of\nexchange rates.<\/p>\n\n<p>What is sent, and when: the three-letter base currency code you have\nconfigured (for example <code>USD<\/code>), sent as part of the request URL --\n    https:\/\/api.exchangerate-api.com\/v4\/latest\/{BASE_CURRENCY} -- when you\npress \"Sync rates\" in the admin panel, when you run <code>wp mhmcs rates-sync<\/code>\nfrom the command line, and on the schedule you configure under automatic\nrate updates (hourly, twice daily, or daily). No other data from your site\nis included.<\/p>\n\n<p>Terms of service and privacy policy: https:\/\/www.exchangerate-api.com\/terms\n(ExchangeRate-API publishes its privacy policy inside that same page rather\nthan on a separate one.)<\/p>\n\n<p><strong>European Central Bank (ECB) daily reference rates<\/strong><\/p>\n\n<p>What it is: the ECB's public daily reference-rate feed, used as the fallback\nwhen ExchangeRate-API cannot be reached.<\/p>\n\n<p>What is sent, and when: nothing beyond the User-Agent described above. The\nfeed is a fixed, parameter-free address --\n    https:\/\/www.ecb.europa.eu\/stats\/eurofxref\/eurofxref-daily.xml -- so no\ncurrency code or other value is sent to the ECB; the same document is\nreturned to every requester. It is only requested when ExchangeRate-API's\nrequest has failed. The feed is EUR-based and covers roughly thirty\ncurrencies rather than the hundreds ExchangeRate-API carries. If your base\ncurrency is outside that set, this source returns nothing at all and your\nexisting rates are left unchanged until the next attempt; if only one of\nyour configured target currencies is outside that set, the other target\ncurrencies still update and the unsupported one is simply left without a\nrate from this source.<\/p>\n\n<p>The ECB does not publish a document titled \"Terms of Service.\" Its terms of\nuse are stated on its Disclaimer &amp; Copyright page, which is the closest\nequivalent and is linked below.<\/p>\n\n<p>Disclaimer &amp; Copyright (terms of use): https:\/\/www.ecb.europa.eu\/services\/using-our-site\/disclaimer\/html\/index.en.html\nPrivacy statement: https:\/\/www.ecb.europa.eu\/services\/data-protection\/privacy-statements\/html\/ecb.privacy_statement_website.en.html<\/p>\n\n<p>The ECB's reference-rates page separately states that using these rates for\ntransaction purposes is strongly discouraged:\nhttps:\/\/www.ecb.europa.eu\/stats\/policy_and_exchange_rates\/euro_reference_exchange_rates\/html\/index.en.html\nThat page, not the two links above, is the source of that caution. This\nplugin uses the feed to convert prices for display and checkout, which is\nthe kind of transactional use that notice is about; if that matters for your\nshop, review that page before relying on this fallback.<\/p>\n\n<p><strong>Redirecting a source<\/strong><\/p>\n\n<p>If your network blocks the ECB feed, the <code>mhmcs_fallback_rates_url<\/code> filter\nreceives the URL, the base currency code and which source is being filtered\n-- always <code>'ecb'<\/code>, since ECB is now the only fallback -- so the request can\nbe pointed elsewhere.<\/p>\n\n<p><strong>Visitor geolocation (through WooCommerce)<\/strong><\/p>\n\n<p>When \"Enable geolocation-based currency detection\" is switched on, the plugin\nasks WooCommerce which country a visitor is in, using WooCommerce's own\n    WC_Geolocation API. Depending on how your site is configured, WooCommerce\nanswers that either from a local MaxMind database or by contacting the remote\ngeolocation service it is configured to use \u2014 the request and the service are\nWooCommerce's, not this plugin's, and this plugin sends nothing itself. The\nsetting is off unless you turn it on.<\/p>\n\n<p>WooCommerce geolocation documentation:\nhttps:\/\/woocommerce.com\/document\/maxmind-geolocation-integration\/<\/p>\n\n<h3>Source code<\/h3>\n\n<p>The settings screen is a React application, and what ships inside the plugin is\nthe compiled bundle at <code>admin-app\/build\/index.js<\/code>. The readable source it is\nbuilt from is not in the package, so here is where to find it and how to\nreproduce the build.<\/p>\n\n<p>Full source, including the unminified JavaScript:\nhttps:\/\/github.com\/MaxHandMade\/mhm-currency-switcher<\/p>\n\n<p>The source of the bundle is <code>admin-app\/src\/<\/code>. It is compiled with WordPress's\nown build tooling, @wordpress\/scripts, and nothing else:<\/p>\n\n<pre><code>npm install\nnpm run build\n<\/code><\/pre>\n\n<p>That writes <code>admin-app\/build\/index.js<\/code> together with the <code>index.asset.php<\/code>\ndependency map the plugin reads when enqueuing the script. No other build step,\nminifier or bundler is involved, and no code is generated at install time or at\nruntime.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>mhm-currency-switcher<\/code> folder to the <code>\/wp-content\/plugins\/<\/code> directory, or install directly through the WordPress plugin screen.<\/li>\n<li>Activate the plugin through the 'Plugins' screen in WordPress.<\/li>\n<li>Make sure WooCommerce is installed and activated.<\/li>\n<li>Go to <strong>WooCommerce &gt; MHM Currency<\/strong> to configure your currencies and exchange rates.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"what%20are%20the%20shortcodes%3F\"><h3>What are the shortcodes?<\/h3><\/dt>\n<dd><p>[mhmcs_currency_switcher] renders the currency dropdown. It accepts one\nattribute, <code>size<\/code>, which may be <code>small<\/code>, <code>medium<\/code> or <code>large<\/code>; leave it out to\nuse the size saved in Display Options.<\/p>\n\n<pre><code>[mhmcs_currency_prices] renders the same product price in several currencies.\n<\/code><\/pre>\n\n<p>Its attributes are all optional:<\/p>\n\n<ul>\n<li><code>currencies<\/code> \u2014 comma-separated codes, e.g. <code>currencies=\"USD,EUR\"<\/code>. Without\nit, the currencies chosen in Display Options are used. Codes you have not\nconfigured as currencies are ignored.<\/li>\n<li><code>product_id<\/code> \u2014 price a specific product instead of the one being viewed.<\/li>\n<li><code>price<\/code> \u2014 price a specific amount instead of a product's.<\/li>\n<li><code>show_flags<\/code> \u2014 <code>true<\/code> or <code>false<\/code>, overriding the saved Display Options\nsetting.<\/li>\n<\/ul>\n\n<p>Both are also available as Elementor widgets.<\/p><\/dd>\n<dt id=\"how%20many%20currencies%20can%20i%20add%3F\"><h3>How many currencies can I add?<\/h3><\/dt>\n<dd><p>As many as your shop needs \u2014 every currency WooCommerce offers can be enabled,\nand nothing is held back for a paid version. The REST API refuses a request\ncarrying more than 500 currency rows; that is a guard against oversized payloads\nand is well above the number of codes WooCommerce itself offers, so the panel\ncannot reach it.<\/p><\/dd>\n<dt id=\"how%20are%20exchange%20rates%20fetched%3F\"><h3>How are exchange rates fetched?<\/h3><\/dt>\n<dd><p>Exchange rates are fetched from ExchangeRate-API in real time, either on demand or on a schedule you configure (hourly, twice daily, or daily) so your rates stay current without manual intervention.<\/p>\n\n<p>If that source cannot be reached, the plugin falls back to the European Central Bank's daily reference rate feed before giving up and leaving your existing rates in place. Both are named, with their terms, under \"External services\" below. If your network blocks the fallback, the <code>mhmcs_fallback_rates_url<\/code> filter can point it somewhere else.<\/p><\/dd>\n<dt id=\"is%20the%20plugin%20compatible%20with%20woocommerce%20hpos%3F\"><h3>Is the plugin compatible with WooCommerce HPOS?<\/h3><\/dt>\n<dd><p>Yes. MHM Currency Switcher fully supports WooCommerce High-Performance Order Storage (HPOS \/ Custom Order Tables).<\/p><\/dd>\n<dt id=\"can%20a%20per-product%20fixed%20price%20be%20a%20sale%20price%3F\"><h3>Can a per-product fixed price be a sale price?<\/h3><\/dt>\n<dd><p>No. A fixed price is stored per product and currency, not per price type, so the same amount is used for the regular price and the sale price. A product on sale in your base currency shows as not on sale in a currency you have given a fixed price to. If you need the sale to carry across, leave that currency to the exchange rate instead of fixing it.<\/p><\/dd>\n<dt id=\"is%20there%20a%20limit%20on%20how%20often%20the%20conversion%20endpoint%20can%20be%20called%3F\"><h3>Is there a limit on how often the conversion endpoint can be called?<\/h3><\/dt>\n<dd><p>Yes. When cache compatibility mode is on, prices on cached pages are converted through a public REST endpoint, and one address may call it 120 times a minute by default. Ordinary browsing is nowhere near that \u2014 a page makes one request. If your shop sits behind a reverse proxy or a CDN that makes every visitor look like the same address, raise or disable the limit with the <code>mhmcs_convert_rate_limit<\/code> filter. Note that the address is read from the proxy headers WooCommerce passes on, which it trusts unconditionally and which can be forged; the limit bounds accidental hammering rather than a determined attacker.<\/p><\/dd>\n<dt id=\"i%20see%20a%20warning%20that%20cache%20compatibility%20is%20not%20being%20applied.%20what%20is%20it%3F\"><h3>I see a warning that cache compatibility is not being applied. What is it?<\/h3><\/dt>\n<dd><p>Some themes and plugins define WooCommerce's cart constant on every page, usually to show a cart total in the header. When that happens the plugin treats every page as a checkout \u2014 the customer's money is at stake \u2014 and converts prices on the server, which is exactly what cache compatibility mode exists to avoid. Nothing looks wrong on the site: prices are still correct for whoever loads the page first, and then a page cache can serve that person's currency to everyone else. Because there is no visible symptom, the plugin says so in the admin instead. The notice clears itself as soon as a front-end page renders normally again.<\/p><\/dd>\n<dt id=\"why%20does%20the%20structured%20data%20show%20a%20different%20currency%20from%20the%20price%20on%20the%20page%3F\"><h3>Why does the structured data show a different currency from the price on the page?<\/h3><\/dt>\n<dd><p>With cache compatibility on, the page is generated in your base currency and the browser converts the prices afterwards, so the machine-readable product data a crawler reads stays in the base currency. This is deliberate and is not corrected: pinning it the other way would leave the data disagreeing with the page in the one case where the two currently agree \u2014 with cache compatibility switched off, where the page and the structured data are both converted on the server.<\/p><\/dd>\n<dt id=\"does%20the%20woocommerce%20rest%20api%20return%20converted%20prices%3F\"><h3>Does the WooCommerce REST API return converted prices?<\/h3><\/dt>\n<dd><p>Only when the request asks for a currency: <code>?currency=EUR<\/code> on a <code>wc\/v3<\/code> product request converts <code>price<\/code>, <code>regular_price<\/code> and <code>sale_price<\/code> and adds a <code>currency_code<\/code> field. Without the parameter the response is pinned to your base currency, so the answer never depends on the cookies of whoever is calling. A per-product fixed price takes precedence over the exchange rate here, exactly as it does on the shop page.<\/p>\n\n<p>One known limit: the <code>price_html<\/code> field is not pinned in the same way. It cannot be reached in that state by a normal <code>wc\/v3<\/code> client \u2014 only by code that dispatches an internal REST request during a page render \u2014 so no integration sees it, but it is not consistent with the three numeric fields and is recorded here rather than left unsaid.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>2.1.0<\/h4>\n\n<ul>\n<li>BREAKING: switcher CSS classes were renamed from <code>mhm-cs-*<\/code> to <code>mhmcs-*<\/code>.\nEvery class in the switcher's CSS and JS -- <code>.mhm-cs-switcher<\/code>,\n  .mhm-cs-dropdown, <code>.mhm-cs-size--small<\/code>, and the rest -- now uses the\n  mhmcs- prefix instead. If you have written custom CSS or JavaScript\nthat targets one of the old <code>mhm-cs-*<\/code> classes, it will stop matching\nafter you update: change your selectors to the new <code>mhmcs-<\/code> names. No\nalias is kept for the old classes.<\/li>\n<li>BREAKING: the <code>mhmcs_fallback_rates_url<\/code> filter's <code>$source<\/code> argument is\nnow always <code>ecb<\/code>. The exchange-rate fallback no longer has two stages\n(<code>currency-api<\/code> then <code>frankfurter<\/code>); it is now a single request to the\nEuropean Central Bank's daily reference feed. Code that checked for\n  $source === 'currency-api' or <code>'frankfurter'<\/code> will no longer see those\nvalues.<\/li>\n<li>BREAKING: the settings migration for sites still on a pre-1.0.0 install\nwas removed, along with its matching legacy-license cleanup and the\nequivalent old-option branches in the uninstall routine. Every version\nreleased since 1.0.0 (2026-07) is unaffected; only a site that has never\nupdated past the 2026-03 release would have skipped a migration it\notherwise would have received on activation.<\/li>\n<li>Changed: the exchange-rate fallback is now a single European Central Bank\nrequest instead of the two-stage <code>currency-api.pages.dev<\/code> then\nFrankfurter chain added in 2.0.0. Coverage is unchanged -- the same\nroughly thirty currencies -- because that was already the final stage of\nthe old chain; the extra intermediate stage is removed as no longer\nuseful.<\/li>\n<li>Added: a snooze option for the two cache-compatibility admin notices.\nDismissing a notice now clears it only for the specific problem currently\ndetected -- it comes back automatically if a new, different cache problem\nappears later, instead of going silent for good.<\/li>\n<li>Added: the WooCommerce-missing notice and both cache-compatibility\nnotices now only appear on the screens where they belong, instead of on\nevery admin screen. Capability requirements differ by notice: the\nWooCommerce-missing notice needs <code>activate_plugins<\/code> (the capability to\nact on it -- you install a plugin), and the two cache-compatibility\nnotices need <code>manage_woocommerce<\/code>.<\/li>\n<li>Fixed: every remaining <code>mhm-cs-<\/code> \/ <code>mhm_cs_<\/code> \/ <code>mhm_currency_switcher_<\/code>\nlegacy naming token still in the plugin -- across CSS, JavaScript, the\nadmin panel source and its compiled build, tests and documentation -- has\nbeen renamed to the current <code>mhmcs<\/code> prefix. This is the last of the\nprefix cleanup that started with the 2.0.0 shortcode and option rename.<\/li>\n<li>Fixed: the public, unauthenticated <code>GET \/rates<\/code> REST endpoint was\nremoved. It duplicated information already visible in the page itself;\nthe authenticated <code>\/rates\/sync<\/code> and <code>\/rates\/preview<\/code> endpoints used by\nthe admin panel are unaffected.<\/li>\n<li>For developers: <code>languages\/<\/code> is no longer included in the release ZIP --\nWordPress.org compiles translations from the <code>.pot<\/code> file, which is still\nkept in the plugin's repository.<\/li>\n<\/ul>\n\n<h4>2.0.0<\/h4>\n\n<ul>\n<li>BREAKING: the two shortcode tags were renamed. <code>[mhm_currency_switcher]<\/code>\nis now <code>[mhmcs_currency_switcher]<\/code>, and <code>[mhm_currency_prices]<\/code> is now\n  [mhmcs_currency_prices]. The old tags are gone; a page still holding one\nwill show the raw text instead of the switcher, so update any page, post or\ntemplate that uses them. WordPress.org's prefix check splits a prefix at the\nfirst underscore, which read the old tags as \"mhm\" -- three letters, under\nthe four-letter minimum -- and a plugin cannot be reviewed under a name the\nreview tool cannot attribute to it. Stored data is untouched: option names,\norder meta and per-product fixed prices all keep the names they had.<\/li>\n<li>Changed: the fallback exchange rate source is served from a different host.\nRates now fall back to <code>latest.currency-api.pages.dev<\/code> instead of the\njsDelivr CDN. Same upstream project, same payload; only the host changed.\nWordPress.org's review tool keeps a fixed list of public CDN domains and\ntreats a shipped source naming one as an error, whatever the URL fetches.\nIf your store restricts outbound requests to an allow-list, permit the new\nhost -- or redirect it with the filter below.<\/li>\n<li>Added: a SECOND fallback rate source, so a blocked network is no longer a\ndead end. The host serving the first fallback is unreachable from some\nnational networks -- Turkey, measured -- and not merely by DNS: resolving it\nover DNS-over-HTTPS and connecting straight to the real addresses with the\ncorrect SNI still times out, while other hosts on the same infrastructure\nanswer normally. A server there cannot route around it by changing\nresolvers, the old host cannot be restored (that is the rule above), and the\nupstream project documents no third mirror. The chain now ends at\nFrankfurter, a different provider serving European Central Bank reference\nrates: no API key, commercial use permitted, no attribution required. The\ntrade is coverage -- around thirty currencies rather than hundreds -- which\nis the right trade for a source reached only after two others have failed,\nand the set includes the currencies shops actually price in.<\/li>\n<li>Added: a filter, <code>mhmcs_fallback_rates_url<\/code>, which receives the URL, the base\ncurrency code and which source is being filtered (<code>currency-api<\/code> or\n  frankfurter), so a store can move one source without moving the others.<\/li>\n<li>Added: an About tab, with links to the documentation site, the WordPress.org\nsupport forum and the issue tracker, plus how to reach the developer.<\/li>\n<li>Added: the Advanced tab now says WHEN the next automatic rate update is due,\nnot only how often it repeats. It gives the scheduled time in the store's own\ntimezone and format, how long that is from now, and states plainly that\nWordPress runs scheduled work on the first visit after that time rather than\nexactly on the hour.<\/li>\n<li>Fixed: currencies with no minor unit, or with three, were given two decimals.\nWhen a currency carried no explicit decimal setting the fallback was a fixed\n2 rather than the store's own configuration, so a shop adding JPY saw\n100.00 and one adding BHD lost a digit. The table is derived from ICU's\nminor-unit data; 37 of the 163 codes WooCommerce offers are not\ntwo-decimal currencies. No <code>intl<\/code> extension is required.<\/li>\n<li>Fixed: the Advanced tab claimed nothing was scheduled right after it\nscheduled something. Switching from \"Manual only\" to a recurring interval\nand saving armed the event, but the panel kept the schedule it had read when\nthe page loaded and showed \"Automatic updates are switched on, but no update\nis scheduled. Re-save this setting to schedule one.\" Re-saving changed\nnothing; only reloading the page did. The save response now carries the\nschedule it armed.<\/li>\n<li>Fixed: saving unrelated settings moved the next rate update. The panel sends\nthe whole settings form, and the scheduler asked whether the interval had\nbeen submitted rather than whether it had changed -- so toggling anything on\nthat screen re-armed the event at the current moment, shifting a daily\nstore's update time and making the next visit run a full sync. Saving now\nreconciles the schedule with the stored interval instead: it re-arms on a\nreal change, restores an event that has gone missing while the setting still\npromises one, and clears one left standing behind \"Manual only\".<\/li>\n<li>Fixed: rate-limited responses (HTTP 429) from the public conversion endpoint\ncarried no cache headers, so a proxy or page cache could store a rejection\nand serve it to callers who were not over the limit.<\/li>\n<li>Fixed: the admin styles for the per-currency price fields on the product and\nvariation screens moved out of the markup and into a stylesheet.<\/li>\n<li>Fixed: a translator note on one admin message was placed where the linter\ncould not see it, so that string had been shipping without its note attached.<\/li>\n<li>For developers: the plugin's source and build steps are now named in\nreadme.txt, and every URL the About tab shows is a plain link with no\ntracking parameters.<\/li>\n<\/ul>\n\n<h4>1.3.1<\/h4>\n\n<ul>\n<li>Fixed: a currency with no usable exchange rate could still be used for\nprices, and the amount and the currency it was shown in came from different\ndecisions. A currency added in the panel starts at a rate of 0 until the\nfirst sync, and a per-product fixed price was applied under it while the\nsymbol and code fell back to the base currency -- a foreign amount wearing\nthe base currency's identity, on the catalogue and in the cart and the\ncharge. Such a currency now resolves to the base currency everywhere, which\nis what the panel already said would happen.<\/li>\n<li>Fixed: the WooCommerce REST API (wc\/v3) applied a per-product fixed price for\nthat same unusable currency when one was asked for with <code>?currency=<\/code>, while\nevery other field in the response, and the currency a client reads it under,\nstayed in the base currency. Feeds, stock syncs and marketplace integrations\ntook that price as fact.<\/li>\n<li>Fixed: orders placed in the shop's own currency recorded an exchange rate of\n\n<ol>\n<li>That field is the record of what the customer was charged, so anything\nreconstructing it -- a report, an accounting export, a refund -- had nothing\nto work from. New orders record a rate of 1. Orders already placed keep the\nvalue they were saved with.<\/li>\n<\/ol><\/li>\n<li>Fixed: a save that never reached the database was reported as a success.\nThis affected the currency list, the settings screen, and all three ways\nrates are synced -- the panel button, the hourly schedule and WP-CLI -- and\nin the sync case the \"last synced\" time moved forward regardless, so the\npanel said the rates were current while it served the old ones. Every one of\nthem now reports the failure, and saving again with nothing changed is still\nreported as a success.<\/li>\n<li>Fixed: upgrading from a pre-0.3.0 version could lose the currency\nconfiguration. The migration copied the old settings across, then deleted\nthe originals and marked itself finished -- without checking that the copy\nhad been written. If it had not, there was nothing left and nothing tried\nagain. It now leaves everything in place and retries on the next request.<\/li>\n<li>Fixed: the rate, fee and rounding fields accepted numbers that cannot be\nstored -- text, a value too large to represent, or a negative rate -- and a\nsingle one of them discarded every other currency in the same save. They are\nnow corrected and the panel names each correction, as it already did for the\ndecimal count.<\/li>\n<li>Fixed: a per-product fixed price entered as a number too large to represent\nwas stored in a form that reads back as zero, which offered the product for\nnothing in that currency. A negative fixed price was accepted as well. Both\nare now refused, on the product page and the variation rows alike.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Added: the settings screen was rebuilt. Currencies are now one table where\neach row carries its own rate, fee and rounding controls and shows the price\na customer would actually see in that currency \u2014 computed on the server with\nthe store's own price formatter, not estimated in the browser.<\/li>\n<li>Added: a number format editor per currency \u2014 symbol, symbol position,\ndecimals, and the decimal and thousand separators. WooCommerce stores one set\nof these for the whole shop because it assumes one currency; this plugin\nshows several. Until now the data was stored but there was no field to edit\nit with, so a currency saved with the wrong symbol \u2014 which happens when\nanother multi-currency plugin is filtering WooCommerce at the time \u2014 could\nnot be corrected from the panel at all.<\/li>\n<li>Added: a rate freshness indicator, on each currency row and on the Advanced\ntab. Where no sync has been recorded it says exactly that \u2014 \"No sync\nrecorded yet\" \u2014 rather than claiming a sync never ran, so a shop upgrading to\nthis version is not told its working rates are missing.<\/li>\n<li>Added: an option, off by default, to delete all of the plugin's data when the\nplugin is removed. Left off, your settings and the currency and exchange rate\nrecorded on each order survive uninstalling. Those records are the only basis\nfor multi-currency sales history and cannot be rebuilt afterwards. On a\nmultisite network the switch clears the site the plugin is removed from.<\/li>\n<li>Added: the \"How to use\" tab now documents the navigation menu item, and says\nplainly that Appearance \u2192 Menus only appears when the active theme supports\nmenus or widgets, which most block themes do not.<\/li>\n<li>Added: Turkish translations for everything above.<\/li>\n<li>Fixed: an exchange rate below 1 could not be typed into the panel. Typing\n0.0211 left 211 in the field, and 0.05 left 5, without warning. A shop whose\nbase currency is weaker than the currencies it sells in has no rate above 1,\nso the field could not take a single realistic value. The rate, fee and\nrounding amounts were all affected, in 1.2.0 as well. All of them now keep\nwhat you type.<\/li>\n<li>Fixed: the switcher preview on Display Options left out the base currency and\nignored the \"show currency symbol\" toggle, so it showed a different list from\nthe one a visitor gets. It now matches. The product price widget's currency\nfield, separately, shows how many of its five allowed currencies are chosen.<\/li>\n<li>Fixed: the product price list's five-currency limit was enforced only in the\nbrowser. A sixth currency sent to the REST API was stored and then silently\ndropped when the list rendered. The server now applies the same limit and\nreports it instead of dropping the extra quietly.<\/li>\n<li>Fixed: a variable product's advertised price range could be served from an\nold exchange rate. WooCommerce caches that range for up to 30 days, keyed by\na hash this plugin only put the currency code into \u2014 so after a rate update\nthe range kept coming from the old rate while every other price on the site\nused the new one. A shopper could read one range and be charged more than its\ntop end. The key now includes the rate and rounding the amounts depend on.<\/li>\n<li>Fixed: <code>GET \/settings<\/code> returned the whole stored option, including keys whose\ncontrols were removed in an earlier release. One of them, <code>provider_api_key<\/code>,\nis a credential you supplied. Saving settings has always dropped those keys,\nbut a shop that had not pressed Save since then still held the value, and the\nread route handed it to anyone with the \"manage WooCommerce\" capability \u2014\nwhich includes shop managers, who are not administrators. The read route now\nfilters the same list the save route and the uninstaller do.<\/li>\n<li>Fixed: the currency picker's popover did not close on Escape, and closing it\ndid not return keyboard focus to the button that opened it.<\/li>\n<li>Fixed: values typed into the new format fields are corrected rather than\nsilently accepted \u2014 a separator longer than one character, a decimal count\noutside 0 to 4, or identical thousand and decimal separators \u2014 and the screen\nnames every correction it made instead of changing your input without saying.<\/li>\n<li>Changed: the REST API now refuses a save or preview request carrying more than\n500 currency rows, rather than accepting a payload of any size. The panel\ncannot produce such a request \u2014 WooCommerce offers 163 currency codes in\ntotal \u2014 so the guard only fires on something that did not come from it.<\/li>\n<li>Changed: the settings screen is wider, 1200px rather than 900px. Below that\nwidth the currency table stacks into one card per currency, each field\nlabelled, rather than being cut off at the edge.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Added: a \"How to use\" tab in the plugin's settings screen. The plugin can be\nplaced in five different ways \u2014 two shortcodes, two Elementor widgets and a\nnavigation menu item \u2014 and none of them were named anywhere in the admin, so\nafter adding currencies there was nothing to tell you why the switcher had\nnot appeared on your site. The new tab lists every option with copyable code,\na table of the price-list shortcode's attributes, and a note that the\nAppearance \u2192 Menus route only exists on classic themes.<\/li>\n<li>Fixed: five labels in the currency picker on the settings screen were written\nin Turkish, so they stayed Turkish in every other language, English included.\nThey are English now, and the Turkish wording moved into the Turkish\ntranslation file.<\/li>\n<li>Fixed: the navigation menu switcher printed its CSS class twice in the menu\nitem's class attribute. This was not visible on the storefront, but it was\nwrong.<\/li>\n<li>Fixed: when your browser does not allow a page to write to the clipboard, the\ncopy buttons on the new tab select the code and tell you to copy it. That\nmessage named a Windows keystroke; it no longer names a key at all.<\/li>\n<\/ul>\n\n<h4>1.1.3<\/h4>\n\n<ul>\n<li>Fixed: upgrading from a version older than 0.3.0 reset the plugin's settings,\nand on a shop that had configured currencies it lost the currency list\nentirely. The option names changed in 0.3.0 without a migration, and the\ncurrent names are only written when the plugin is activated \u2014 which does not\nhappen during an in-place update. A one-time migration now carries the old\nsettings and any configured currencies onto the current names, removes the\nold rows, and cancels the pre-0.3.0 rate-update task so it cannot keep firing.\nSites that never configured anything simply get the standard defaults: the\nfour currency codes the old installer wrote were in a format the plugin could\nnever read, so they were never in use and are not carried over.<\/li>\n<li>Fixed: the Advanced tab showed \"Daily\" as the automatic rate-update interval\non sites that had never chosen one, but nothing was scheduled \u2014 the setting\nscreen and the scheduler disagreed about what an unset interval means. The\nscreen now shows \"Manual only\", which is what the plugin actually does until\nyou pick an interval.<\/li>\n<li>Fixed: the multi-currency price display showed prices for currencies you had\nnot configured, and the figure it showed was the base price wearing the other\ncurrency's code and flag. On a shop with nothing configured, the Elementor\nprice widget did this out of the box, because its default currency list is\nUSD, EUR, GBP. Currencies you have not configured are now left out.<\/li>\n<li>Documented the <code>[mhm_currency_switcher]<\/code> and <code>[mhm_currency_prices]<\/code>\nshortcodes and their attributes, which this file advertised but never named.<\/li>\n<li>Fixed: on a shop running a second currency plugin, adding a currency could\nsave it with the wrong symbol \u2014 every new currency picked up the symbol of\nwhichever currency was being displayed, so a US Dollar currency could print\nyour base currency's sign on the storefront. New currencies now take their\nsymbol from WooCommerce's own currency table. Currencies added before this\nrelease keep whatever symbol was stored; if one of yours shows the wrong\nsign, remove it and add it again.<\/li>\n<\/ul>\n\n<h4>1.1.2<\/h4>\n\n<ul>\n<li><strong>Requires WordPress 6.6.<\/strong> The settings screen never loaded on 6.0 to 6.5:\nthe admin bundle depends on a script handle WordPress only registers from\n6.6, and an unregistered dependency makes WordPress drop the script silently.\nEvery release to date claimed 6.0 and none of them could show that screen on\nit. If you are on an older WordPress, staying on 1.1.1 keeps the storefront\nworking \u2014 the conversion scripts have no such dependency \u2014 but the settings\nscreen will not open there either.<\/li>\n<li>Fixed: every control in the currency table was unnamed for screen readers \u2014\nthe enable toggle, both rate controls, both fee controls and both rounding\ncontrols. Each now says what it changes and which currency it belongs to.<\/li>\n<li>Fixed: the currency picker was announced as an unlabelled button, because its\nvisible label was never associated with the control.<\/li>\n<li>Declared compatibility with the Cart &amp; Checkout Blocks. The plugin already\nworked with them \u2014 they read their amounts from the Store API, which is\nconverted on the server \u2014 but without the declaration WooCommerce warned\nshop owners about the plugin on those screens.<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>The settings screen no longer triggers WordPress's deprecation notice for the\n36px control size; its selects and text fields opt into the 40px size that\nbecomes the default in WordPress 7.1.<\/li>\n<li>Corrected the Plugin URI, which pointed at a page that does not exist.<\/li>\n<li>Declared WooCommerce as a required plugin, and corrected the tested-against\nWooCommerce range to the versions the test suite actually runs (7.4 to 10.9).<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Cache compatibility mode, on by default. Anonymous shop, archive and product\npages are rendered in your base currency so a page cache can serve the same\nHTML to everyone, and the browser converts the displayed prices afterwards.\nCart, checkout, order totals, order emails and the WooCommerce REST API are\nstill converted on the server.<\/li>\n<li>The currency switcher no longer reloads the page when cache compatibility is\non; it sets the cookie, converts the prices in place and refreshes the\nmini-cart.<\/li>\n<li>Fixed: prices were converted on admin screens and in admin AJAX, which could\nwrite a converted price into an order line item.<\/li>\n<li>Fixed: <code>wc\/v3<\/code> REST reads now return the base currency unless the request\nasks for one, so the response no longer depends on the caller's cookies.<\/li>\n<li>Fixed: scheduled tasks and WP-CLI no longer convert prices.<\/li>\n<li>Fixed: cart totals are recalculated when the visitor changes currency, so the\nmini-cart can no longer show an amount from the previous currency.<\/li>\n<li>Fixed: prices inside WooCommerce block themes are no longer overwritten with\nbase amounts after the page has loaded.<\/li>\n<li>Fixed: a percentage fee per currency was never applied, because the admin\nscreen and the sanitiser disagreed on the stored value.<\/li>\n<li>Fixed: a currency with a zero exchange rate no longer falls back to showing\nbase prices as though they were converted.<\/li>\n<li>Fixed: rounding is now applied to shipping, fees and coupon discounts as well\nas product prices.<\/li>\n<li>Fixed: shipping tax is converted along with the shipping amount.<\/li>\n<li>The plugin now warns in the admin when cache compatibility is silently not\nbeing applied, and when a mini-cart is left in the base currency because\nWooCommerce's cart-fragment script is not loaded.<\/li>\n<li>New public REST endpoint <code>POST mhmcs\/v1\/convert<\/code>, rate limited to 120\nrequests a minute per address (<code>mhmcs_convert_rate_limit<\/code> filter).<\/li>\n<li>See \"Known limits\" above for the accepted trade-offs of cache mode.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First public release.<\/li>\n<li>All features are available to everyone: unlimited currencies, automatic\nexchange rate updates, geolocation-based currency detection, fixed\nper-product prices, and a WooCommerce REST API currency filter.<\/li>\n<li>Identifiers renamed to the <code>mhmcs<\/code> prefix. Settings from earlier\ndevelopment builds are not carried over.<\/li>\n<\/ul>","raw_excerpt":"Multi-currency support for WooCommerce. Let your customers browse, shop, and checkout in their preferred currency with real-time exchange rates.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/359893","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=359893"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/maxhandmade"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=359893"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=359893"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=359893"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=359893"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=359893"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=359893"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}