{"id":365278,"date":"2026-09-08T14:59:18","date_gmt":"2026-09-08T14:59:18","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/merchgain-profit-margin-reports-for-woocommerce\/"},"modified":"2026-09-08T14:58:45","modified_gmt":"2026-09-08T14:58:45","slug":"merchgain","status":"publish","type":"plugin","link":"https:\/\/tir.wordpress.org\/plugins\/merchgain\/","author":23551451,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.2.0","stable_tag":"0.2.0","tested":"7.1","requires":"6.7","requires_php":"7.4","requires_plugins":null,"header_name":"Merchgain - Profit & Margin Reports for WooCommerce","header_author":"Baltano","header_description":"Profit and margin reports for WooCommerce, built on the native Cost of Goods Sold field. Reads your store, changes nothing.","assets_banners_color":"0f162a","last_updated":"2026-09-08 14:58:45","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/merchgain.com","header_author_uri":"https:\/\/baltano.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":27,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.2.0":{"tag":"0.2.0","author":"baltano","date":"2026-09-08 14:58:45","revision":3686880}},"upgrade_notice":{"0.2.0":"<p>First public release.<\/p>","0.1.1":"<p>The report now covers your whole order history instead of the last 12 months.<\/p>","0.1.0":"<p>First release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3686878,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3686878,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3686878,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3686878,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3686878,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.2.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3686878,"resolution":"1","location":"assets","locale":"","width":1280,"height":980},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3686878,"resolution":"2","location":"assets","locale":"","width":1280,"height":900},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3686878,"resolution":"3","location":"assets","locale":"","width":1280,"height":520},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3686878,"resolution":"4","location":"assets","locale":"","width":1280,"height":500}},"screenshots":{"1":"Summary cards with the coverage line, and profit per product.","2":"Profit per category.","3":"The missing cost warning, with links straight to the products.","4":"Onboarding shown when the Cost of Goods Sold feature is still off."}},"plugin_section":[],"plugin_tags":[233971,132181,11938,6882,3654],"plugin_category":[],"plugin_contributors":[278694],"plugin_business_model":[],"class_list":["post-365278","plugin","type-plugin","status-publish","hentry","plugin_tags-cogs","plugin_tags-cost-of-goods","plugin_tags-margin","plugin_tags-profit","plugin_tags-reports","plugin_contributors-baltano","plugin_committers-baltano"],"banners":{"banner":"https:\/\/ps.w.org\/merchgain\/assets\/banner-772x250.png?rev=3686878","banner_2x":"https:\/\/ps.w.org\/merchgain\/assets\/banner-1544x500.png?rev=3686878","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/merchgain\/assets\/icon.svg?rev=3686878","icon":"https:\/\/ps.w.org\/merchgain\/assets\/icon.svg?rev=3686878","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/merchgain\/assets\/screenshot-1.png?rev=3686878","caption":"Summary cards with the coverage line, and profit per product."},{"src":"https:\/\/ps.w.org\/merchgain\/assets\/screenshot-2.png?rev=3686878","caption":"Profit per category."},{"src":"https:\/\/ps.w.org\/merchgain\/assets\/screenshot-3.png?rev=3686878","caption":"The missing cost warning, with links straight to the products."},{"src":"https:\/\/ps.w.org\/merchgain\/assets\/screenshot-4.png?rev=3686878","caption":"Onboarding shown when the Cost of Goods Sold feature is still off."}],"raw_content":"<!--section=description-->\n<p>WooCommerce tells you what you sold. It does not tell you what you earned.<\/p>\n\n<p>Since WooCommerce 10.3 the cost of goods sold lives in the core product editor, and every order\nrecords the cost at the moment of sale. Merchgain reads that field and answers the question the\nsales report cannot: how much of this revenue is actually yours. It is a WooCommerce profit report\nbuilt on data your store already has - no import, no second place to keep costs.<\/p>\n\n<p>It only reads. No product, no price, no order, no cost value is ever written back to your store.<\/p>\n\n<h4>What you get<\/h4>\n\n<ul>\n<li><strong>Summary cards<\/strong> - revenue, cost of goods, gross profit and margin for the period you pick.<\/li>\n<li><strong>Profit per product<\/strong> - sortable, searchable, paginated.<\/li>\n<li><strong>Profit per category<\/strong> - the same sales grouped by product category. A product that sits\nin several categories counts in each of them, so category totals can add up to more than\nthe summary - the screen and the CSV file both say so.<\/li>\n<li><strong>Missing cost warning<\/strong> - how many products have no cost recorded, with links straight to\nthe products, and how much of your revenue that leaves uncovered.<\/li>\n<li><strong>CSV export<\/strong> - the current view, exactly as you see it on screen. Very large reports are\ncapped at 20,000 rows and the file says so on its last line, so a short file is never a\nsilent one - and a category export that adds up to more than the summary says why.<\/li>\n<li><strong>Foreign currency warning<\/strong> - orders in a currency other than your store currency are named\nand left out, instead of being quietly added into one wrong total.<\/li>\n<\/ul>\n\n<h4>What makes it different<\/h4>\n\n<ul>\n<li><strong>CSV export in the free version.<\/strong> Not behind an upgrade.<\/li>\n<li><strong>The missing cost warning is a feature, not an upsell.<\/strong> You see coverage next to every\nnumber, so you always know how much of the report rests on real data.<\/li>\n<li><strong>Works without WooCommerce Analytics.<\/strong> Merchgain runs its own queries against the order\ntables, so it does not require the Analytics module to be enabled.<\/li>\n<li><strong>Nothing leaves your server.<\/strong> No account, no external service, no telemetry, no calls home.\nThe report is calculated on your hosting and stays there.<\/li>\n<\/ul>\n\n<h4>How the numbers are calculated<\/h4>\n\n<p>This is a cost of goods sold report, so every number below rests on the cost recorded at the\nmoment of sale - not on a current price list.<\/p>\n\n<p>Revenue is the net line total of sold items after discounts, excluding tax and shipping. Refunds\ncount as negative amounts in the period they were issued, not in the period of the original sale.\nOrders counted by default: completed, processing and refunded.<\/p>\n\n<p>Margin is profit divided by revenue - not markup on cost. A product bought for 60 and sold for\n100 has a 40% margin here. That single distinction is what separates a profit margin report from\na sales report.<\/p>\n\n<p>Profit and margin are calculated only on items whose cost is known. An item with no cost recorded\nstill counts towards revenue, but it is never treated as if it had cost zero - the report says so\ninstead of quietly inflating your margin.<\/p>\n\n<p>Documentation and answers: https:\/\/merchgain.com\/<\/p>\n\n<p>From the makers of Merchlint.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin. WooCommerce 10.3 or newer is required.<\/li>\n<li>Go to WooCommerce -&gt; Settings -&gt; Advanced -&gt; Features and switch on \"Cost of Goods Sold\".<\/li>\n<li>Fill in the cost on your products - the field is in the General tab of the product editor.<\/li>\n<li>Open \"Profit &amp; margin\" in the admin menu - its own item, just below the WooCommerce block.<\/li>\n<\/ol>\n\n<p>New orders record the product cost at the moment of sale, so the report starts filling up from\nthe point where costs are in place.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"how%20is%20margin%20calculated%3F\"><h3>How is margin calculated?<\/h3><\/dt>\n<dd><p>Profit divided by revenue. A product bought for 60 and sold for 100 gives 40 profit and a 40%\nmargin. This is not markup on cost, which for the same product would be 66.7%. The two get mixed\nup often, so the definition is printed under the report as well.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/MARGIN\/<\/p><\/dd>\n<dt id=\"where%20do%20the%20costs%20come%20from%3F\"><h3>Where do the costs come from?<\/h3><\/dt>\n<dd><p>From the Cost of Goods Sold field built into WooCommerce 10.3 and newer. Merchgain does not store\ncosts of its own and does not add a second cost field to your products.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/COGS\/<\/p><\/dd>\n<dt id=\"does%20any%20data%20leave%20my%20server%3F\"><h3>Does any data leave my server?<\/h3><\/dt>\n<dd><p>No. Merchgain makes no outgoing connections at all - no analytics, no licence check, no update\nping of its own. Everything is calculated by your own database and displayed in your own admin.<\/p><\/dd>\n<dt id=\"what%20about%20orders%20placed%20before%20i%20filled%20in%20the%20costs%3F\"><h3>What about orders placed before I filled in the costs?<\/h3><\/dt>\n<dd><p>They have no cost recorded, and Merchgain reports them as \"no cost data\" rather than as a cost of\nzero. Their revenue still counts; they are simply left out of profit and margin, and the coverage\nline tells you how much of your revenue that is.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/FILL\/<\/p><\/dd>\n<dt id=\"my%20product%20genuinely%20costs%20zero%20and%20it%20shows%20up%20as%20missing%20a%20cost.%20why%3F\"><h3>My product genuinely costs zero and it shows up as missing a cost. Why?<\/h3><\/dt>\n<dd><p>Because WooCommerce cannot tell the two apart. Saving a cost of zero - on the product or on an\norder item - makes the core store nothing at all rather than a zero, so \"cost of zero\" and \"no\ncost entered\" end up identical in the database. Rather than guess, Merchgain always says \"no cost\ndata\" and never \"cost 0\". Free samples, giveaways and downloadable extras will therefore appear on\nthe missing cost list.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/ZERO\/<\/p><\/dd>\n<dt id=\"i%20issued%20a%20refund%20and%20my%20historical%20profit%20changed.%20why%3F\"><h3>I issued a refund and my historical profit changed. Why?<\/h3><\/dt>\n<dd><p>That is WooCommerce, not Merchgain. Creating a refund makes the core recalculate the cost of every\nitem on the parent order using the product's cost <em>as it is today<\/em>. If the product cost changed in\nthe meantime, the stored history changes with it. Merchgain reports what is in the database; it\ndoes not silently keep a second copy.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/REWRITE\/<\/p><\/dd>\n<dt id=\"which%20month%20does%20a%20refund%20belong%20to%3F\"><h3>Which month does a refund belong to?<\/h3><\/dt>\n<dd><p>The month the refund was issued, not the month of the original sale. A September sale refunded in\nNovember leaves September untouched and shows as a negative amount in November. Reports of closed\nmonths do not change behind your back.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/REFUND\/<\/p><\/dd>\n<dt id=\"i%20have%20orders%20in%20euros%20and%20dollars.%20what%20happens%20to%20them%3F\"><h3>I have orders in euros and dollars. What happens to them?<\/h3><\/dt>\n<dd><p>They are left out of the report and named in a warning above the numbers. Merchgain does not\nconvert exchange rates, and adding several currencies into one total would produce a number that\nlooks right and is not.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/CURR\/<\/p><\/dd>\n<dt id=\"i%20keep%20my%20costs%20in%20wpfactory%20cost%20of%20goods.%20why%20does%20merchgain%20show%20them%20as%20missing%3F\"><h3>I keep my costs in WPFactory Cost of Goods. Why does Merchgain show them as missing?<\/h3><\/dt>\n<dd><p>Because those costs live in that plugin's own meta fields, not in the WooCommerce core field.\nMerchgain deliberately does not read other plugins' data. Moving the values into the core field\nis on the roadmap as an optional, preview-first import.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/OTHER\/<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20high-performance%20order%20storage%3F\"><h3>Does it work with High-Performance Order Storage?<\/h3><\/dt>\n<dd><p>Yes, and with the classic post-based storage as well. Cost values live in the order items table,\nwhich is the same in both layouts.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/HPOS\/<\/p><\/dd>\n<dt id=\"which%20orders%20are%20counted%3F\"><h3>Which orders are counted?<\/h3><\/dt>\n<dd><p>Completed, processing and refunded. Refunded is in the list on purpose: a full refund flips the\nparent order to that status, and leaving it out would make a fully refunded order count as minus\nits own value instead of zero. WooCommerce Analytics excludes only pending, failed and cancelled\nby default, so this set is one status narrower - it skips on-hold.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/STAT\/<\/p><\/dd>\n<dt id=\"my%20category%20totals%20add%20up%20to%20more%20than%20the%20summary%20card.%20why%3F\"><h3>My category totals add up to more than the summary card. Why?<\/h3><\/dt>\n<dd><p>Because a product that sits in several categories is counted in each of them. A mug in both\n\"Kitchen\" and \"Gifts\" adds its sales to both rows, so the rows add up to more than the store\nactually sold. The alternative - picking one category and dropping the sale from the other -\nwould quietly understate every shared category, which is worse. The summary cards are counted\nfrom the order items themselves, so they are never double counted. The screen says this under\nthe table, and a CSV export of the category view says it on the last line, with both numbers.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/CAT\/<\/p><\/dd>\n<dt id=\"how%20much%20history%20does%20the%20report%20cover%3F\"><h3>How much history does the report cover?<\/h3><\/dt>\n<dd><p>All of it. There is no date limit. Any range can be selected, including a single month from\nyears back; profit and margin appear wherever a cost was recorded on the sold item.<\/p><\/dd>\n<dt id=\"does%20it%20slow%20my%20store%20down%3F\"><h3>Does it slow my store down?<\/h3><\/dt>\n<dd><p>The report runs in the admin only, never on the storefront, and results are cached for an hour.\nEntering a cost in the product editor clears that cache immediately, so the numbers never wait for\na timer. For anything else that changes the figures - an order status, a refund issued elsewhere,\nan import - there is a \"Recalculate\" button next to the export.<\/p><\/dd>\n<dt id=\"who%20can%20see%20the%20report%3F\"><h3>Who can see the report?<\/h3><\/dt>\n<dd><p>Anyone with the \"view WooCommerce reports\" capability, which is the same permission WooCommerce\nuses for its own sales reports. A shop manager has it, and so does a bookkeeper account limited to\nreports only. The report has its own item in the admin menu, \"Profit &amp; margin\", sitting just below\nthe WooCommerce block - not inside the WooCommerce submenu, where an account limited to reports\nwould never see it: that submenu needs a permission such an account does not have.<\/p>\n\n<p>Longer answer: https:\/\/merchgain.com\/r\/PERM\/<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.2.0<\/h4>\n\n<ul>\n<li>First public release. Versions 0.1.0 and 0.1.1 were review builds submitted to the plugin\ndirectory and were never published, so this is the first version anyone can install. The code\nis the one that passed review; only the version number changed.<\/li>\n<\/ul>\n\n<h4>0.1.1<\/h4>\n\n<ul>\n<li>The report no longer limits how far back it reaches. The 365-day window is gone from the\ncode entirely, along with the notice that explained it.<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>First working version: summary cards, profit per product and per category, missing cost\nwarning, CSV export, foreign currency warning, onboarding, cached results with a\nRecalculate button.<\/li>\n<\/ul>","raw_excerpt":"A free WooCommerce profit report built on the native Cost of Goods Sold field. Gross profit and margin per product, category and period.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/365278","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=365278"}],"author":[{"embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/baltano"}],"wp:attachment":[{"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=365278"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=365278"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=365278"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=365278"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=365278"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/tir.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=365278"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}