<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Valcr Blog</title>
        <link>https://docs.valcr.site/blog</link>
        <description>Data insights, product updates, and engineering notes from Valcr.</description>
        <lastBuildDate>Tue, 14 Jan 2025 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>Copyright © 2026 Valcr — Cyntax LLC</copyright>
        <item>
            <title><![CDATA[Introducing the Valcr Data API]]></title>
            <link>https://docs.valcr.site/blog/introducing-valcr-data-api</link>
            <guid>https://docs.valcr.site/blog/introducing-valcr-data-api</guid>
            <pubDate>Tue, 14 Jan 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Valcr opens API access to its financial benchmark intelligence platform. Read about the Data API, VCFS normalisation layer, and how to get started.]]></description>
            <content:encoded><![CDATA[<p>For the past year, we've been building something that has needed to exist for a long time: a financial data infrastructure layer for digital commerce that actually meets the standard that institutions require.</p>
<p>Today, we're opening API access.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-api-gives-you">What the API gives you<a href="https://docs.valcr.site/blog/introducing-valcr-data-api#what-the-api-gives-you" class="hash-link" aria-label="Direct link to What the API gives you" title="Direct link to What the API gives you" translate="no">​</a></h2>
<p>The Valcr Data API serves the same benchmark intelligence that powers the Valcr platform — but programmatically, via authenticated HTTP endpoints, into whatever system you're building or operating.</p>
<p>That means:</p>
<ul>
<li class=""><strong>Benchmark percentiles</strong> — gross margin, revenue growth, LTV<!-- -->:CAC<!-- -->, cart abandonment, AOV, refund rate, and more, broken down by category and segment, updated quarterly</li>
<li class=""><strong>Merchant VCFS profiles</strong> — submit and retrieve structured financial data in the Valcr Commerce Financial Schema</li>
<li class=""><strong>Peer comparisons</strong> — rank a merchant's metrics against their actual peer group, not an industry average from a year-old report</li>
<li class=""><strong>AI-generated insights</strong> — causal narratives that explain <em>why</em> a metric sits where it does, not just <em>where</em> it sits</li>
<li class=""><strong>XBRL export</strong> — structured, taxonomy-tagged financial documents for audit, filing, and ERP integration</li>
</ul>
<p>All of it behind a single base URL: <code>https://api.valcr.site/data/v1</code></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="who-this-is-for">Who this is for<a href="https://docs.valcr.site/blog/introducing-valcr-data-api#who-this-is-for" class="hash-link" aria-label="Direct link to Who this is for" title="Direct link to Who this is for" translate="no">​</a></h2>
<p>We built this for three audiences:</p>
<p><strong>Lenders and underwriters</strong> who need to contextualise a merchant's financials within their real peer group — not a national average, but a p25/p50/p75 distribution computed from verified data from comparable businesses in the same segment.</p>
<p><strong>SaaS platforms and fintech developers</strong> who want to embed benchmark intelligence inside their own products without building or maintaining the underlying dataset. You plug in the API; your users see the intelligence.</p>
<p><strong>Commerce operators and their teams</strong> who want programmatic access to their own VCFS profile, their Valcr Score, and their benchmark position — integrated into internal dashboards, underwriting pipelines, or investor reporting tools.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://docs.valcr.site/blog/introducing-valcr-data-api#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>Authentication is via bearer tokens. Create an API key in the <a href="https://console.valcr.site/" target="_blank" rel="noopener noreferrer" class="">Console</a>, assign the scopes your integration needs, and you're making requests in under two minutes.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-X</span><span class="token plain"> GET </span><span class="token string" style="color:rgb(255, 121, 198)">"https://api.valcr.site/data/v1/benchmarks?category=ecommerce"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Authorization: Bearer vcr_live_your_key_here"</span><br></div></code></pre></div></div>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"category"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ecommerce"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"period"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2024-Q4"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"metrics"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"gross_margin"</span><span class="token operator">:</span><span class="token plain">   </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"p25"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.28</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"p50"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.41</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"p75"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.58</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"p90"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.67</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"revenue_growth"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"p25"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.04</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"p50"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.12</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"p75"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.26</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"p90"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.48</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"sample_size"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">4812</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>The keys are scoped. You choose the access level you need — read-only benchmark access at $29/month, or full merchant intelligence with XBRL export at Enterprise tier. Every key is hashed server-side immediately after creation; we never store the raw value.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-vcfs-layer">The VCFS layer<a href="https://docs.valcr.site/blog/introducing-valcr-data-api#the-vcfs-layer" class="hash-link" aria-label="Direct link to The VCFS layer" title="Direct link to The VCFS layer" translate="no">​</a></h2>
<p>Everything in the API is built on the Valcr Commerce Financial Schema — a canonical data model that maps the financial structures from Shopify, Amazon, WooCommerce, QuickBooks, and public filings into a single consistent representation.</p>
<p>VCFS is the reason the benchmarks are comparable. Without normalisation at the schema level, you're comparing numbers that were calculated differently, for different time periods, with different field definitions. The value of benchmark data scales directly with the rigour of the normalisation underneath it.</p>
<p>You can read the full <a class="" href="https://docs.valcr.site/guides/vcfs-schema">VCFS schema documentation here</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="whats-next">What's next<a href="https://docs.valcr.site/blog/introducing-valcr-data-api#whats-next" class="hash-link" aria-label="Direct link to What's next" title="Direct link to What's next" translate="no">​</a></h2>
<p>The dataset grows every month. Every new connected store, every public filing, every data partnership deepens the benchmark distributions and makes the percentiles more credible. That compounding is the fundamental thesis of the platform.</p>
<p>In the near term:</p>
<ul>
<li class="">Shopify and Amazon SP-API direct integrations for automated VCFS population</li>
<li class="">Monthly benchmark updates (currently quarterly)</li>
<li class="">Expanded geography coverage beyond US and UK</li>
<li class="">Enterprise SLA and dedicated support tier</li>
</ul>
<p><a href="https://console.valcr.site/" target="_blank" rel="noopener noreferrer" class="">Create a free Console account</a> and make your first request today. The <a class="" href="https://docs.valcr.site/quickstart">Quickstart guide</a> will get you there in under two minutes.</p>
<hr>
<p>Questions or integration support: <a href="mailto:api@valcr.site" target="_blank" rel="noopener noreferrer" class="">api@valcr.site</a></p>]]></content:encoded>
            <category>product</category>
            <category>announcement</category>
            <category>api</category>
            <category>benchmarks</category>
        </item>
        <item>
            <title><![CDATA[VCFS: Why Commerce Needs a Financial Data Standard]]></title>
            <link>https://docs.valcr.site/blog/what-is-vcfs</link>
            <guid>https://docs.valcr.site/blog/what-is-vcfs</guid>
            <pubDate>Tue, 07 Jan 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The Valcr Commerce Financial Schema (VCFS) explained: why commerce needs a financial data standard, how it maps to XBRL, and what it enables.]]></description>
            <content:encoded><![CDATA[<p>The ecommerce industry produces enormous volumes of financial data every day. Hundreds of millions of transactions. Revenue figures, margin data, customer counts, return rates, fulfilment metrics.</p>
<p>The problem is not the volume. The problem is that none of it speaks the same language.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-fragmentation-problem">The fragmentation problem<a href="https://docs.valcr.site/blog/what-is-vcfs#the-fragmentation-problem" class="hash-link" aria-label="Direct link to The fragmentation problem" title="Direct link to The fragmentation problem" translate="no">​</a></h2>
<p>Ask ten ecommerce operators what their gross margin is and you will get ten different answers — not because their businesses are different, but because they calculated it differently.</p>
<p>Some include shipping as cost of goods. Some don't. Some report net revenue after returns; others report gross. Some count a customer as "active" if they've purchased in the last 90 days; others use 12 months. Cart abandonment rate means something slightly different in every analytics platform that reports it.</p>
<p>This isn't a data problem. It's a schema problem. There is no agreed standard for what these numbers mean and how they should be calculated — so any comparison across merchants is, at best, approximate.</p>
<p>For an operator benchmarking their business, this is inconvenient. For a lender underwriting a merchant, it is a risk. For an investor evaluating a portfolio company against its peers, it quietly degrades every decision they make.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-vcfs-does">What VCFS does<a href="https://docs.valcr.site/blog/what-is-vcfs#what-vcfs-does" class="hash-link" aria-label="Direct link to What VCFS does" title="Direct link to What VCFS does" translate="no">​</a></h2>
<p>The Valcr Commerce Financial Schema is a canonical data model that maps every significant financial metric in ecommerce to a single, precisely defined field with a documented calculation methodology.</p>
<p>Every record that enters Valcr — from a connected Shopify store, an Amazon Seller Central account, an SEC filing, a Companies House submission, or a manual upload — is normalised to the same structure.</p>
<p>The same field names. The same calculation logic. The same confidence score.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"revenue"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"gross_revenue"</span><span class="token operator">:</span><span class="token plain">  </span><span class="token number">480000</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"net_revenue"</span><span class="token operator">:</span><span class="token plain">    </span><span class="token number">432000</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"currency"</span><span class="token operator">:</span><span class="token plain">       </span><span class="token string" style="color:rgb(255, 121, 198)">"USD"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"margins"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"gross_margin"</span><span class="token operator">:</span><span class="token plain">     </span><span class="token number">0.52</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"operating_margin"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.14</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"net_margin"</span><span class="token operator">:</span><span class="token plain">       </span><span class="token number">0.09</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"customers"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"active_customers"</span><span class="token operator">:</span><span class="token plain">          </span><span class="token number">3840</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"average_order_value"</span><span class="token operator">:</span><span class="token plain">       </span><span class="token number">125</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"customer_ltv"</span><span class="token operator">:</span><span class="token plain">              </span><span class="token number">310</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"customer_acquisition_cost"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">48</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"cart_abandonment_rate"</span><span class="token operator">:</span><span class="token plain">     </span><span class="token number">0.66</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"repeat_purchase_rate"</span><span class="token operator">:</span><span class="token plain">      </span><span class="token number">0.38</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>The definitions matter. VCFS specifies:</p>
<ul>
<li class=""><code>gross_margin</code> = <code>(net_revenue - COGS) / net_revenue</code> — not revenue minus all costs, not including shipping as COGS unless it's a core fulfilment cost</li>
<li class=""><code>active_customers</code> = unique customers with at least one order in the reporting period — not monthly actives, not email list size</li>
<li class=""><code>cart_abandonment_rate</code> = <code>abandoned_carts / initiated_carts</code> where "initiated" means at least one item added — not page views on the cart</li>
</ul>
<p>These distinctions sound pedantic. In practice, they are the difference between a benchmark that means something and a number that sounds authoritative but is actually noise.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-xbrl">Why XBRL<a href="https://docs.valcr.site/blog/what-is-vcfs#why-xbrl" class="hash-link" aria-label="Direct link to Why XBRL" title="Direct link to Why XBRL" translate="no">​</a></h2>
<p>VCFS maps directly to XBRL taxonomy elements. This is not an accident.</p>
<p>XBRL (eXtensible Business Reporting Language) is the global standard for structured financial data exchange — the format used by the SEC, Companies House, and financial regulators in over 50 jurisdictions. When a company files with the SEC, the data is tagged in XBRL so systems can automatically process and compare it without parsing prose documents.</p>
<p>By anchoring VCFS to XBRL, Valcr makes it possible to:</p>
<ul>
<li class="">Export merchant financial data as a standards-compliant XBRL document for regulatory submission or audit</li>
<li class="">Compare ecommerce operator data directly against public company filings in the same taxonomy</li>
<li class="">Integrate into ERP and accounting systems that already speak XBRL</li>
</ul>
<p>The <a class="" href="https://docs.valcr.site/api/xbrl">XBRL export endpoint</a> takes a merchant's VCFS submission and returns a fully tagged XBRL instance document. Validated against our published taxonomy. Readable by any XBRL processor.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-benchmark-value-chain">The benchmark value chain<a href="https://docs.valcr.site/blog/what-is-vcfs#the-benchmark-value-chain" class="hash-link" aria-label="Direct link to The benchmark value chain" title="Direct link to The benchmark value chain" translate="no">​</a></h2>
<p>The reason VCFS matters for benchmarking specifically is this: the value of a percentile distribution is entirely dependent on the consistency of the underlying data.</p>
<p>If your benchmark says the median gross margin for ecommerce fashion businesses is 44%, that number is only useful if every business in the sample calculated gross margin the same way. If half of them included fulfilment costs and half didn't, the 44% is a blend of two different things — and benchmarking against it tells you almost nothing.</p>
<p>VCFS eliminates that uncertainty. Every merchant in the Valcr benchmark pool has had their data normalised to the same schema with the same calculation rules. The p50 means the median of businesses where gross margin was calculated identically. That's what makes it a useful number.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-started-with-vcfs">Getting started with VCFS<a href="https://docs.valcr.site/blog/what-is-vcfs#getting-started-with-vcfs" class="hash-link" aria-label="Direct link to Getting started with VCFS" title="Direct link to Getting started with VCFS" translate="no">​</a></h2>
<p>If you're a developer integrating Valcr into a platform, start with the <a class="" href="https://docs.valcr.site/guides/vcfs-schema">VCFS Schema guide</a> — it documents every field, the calculation methodology, and the completeness scoring system that indicates how much of the schema a given merchant submission covers.</p>
<p>If you're an operator, the completeness score is worth understanding. VCFS submissions are scored 0–1. Higher completeness unlocks more granular benchmarking, AI insights, and the Valcr Score composite. A minimum viable submission (net revenue + gross margin) scores around 0.30. A fully populated profile with customer economics and channel breakdown scores above 0.85 and unlocks XBRL export.</p>
<p>The schema is open. The benchmark data that results from it is proprietary — and becomes more valuable with every additional record that enters the normalisation pipeline.</p>
<hr>
<p>Read the full <a class="" href="https://docs.valcr.site/guides/vcfs-schema">VCFS schema documentation →</a></p>]]></content:encoded>
            <category>vcfs</category>
            <category>data</category>
            <category>benchmarks</category>
            <category>infrastructure</category>
        </item>
        <item>
            <title><![CDATA[How the Valcr Score Works]]></title>
            <link>https://docs.valcr.site/blog/how-valcr-score-works</link>
            <guid>https://docs.valcr.site/blog/how-valcr-score-works</guid>
            <pubDate>Wed, 18 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[How the Valcr Score is constructed: five components, weightings, grade bands, and what the composite tells you that individual metrics don't.]]></description>
            <content:encoded><![CDATA[<p>A single number summarising a merchant's financial health is a dangerous thing if constructed carelessly. It can flatten important nuance, reward the wrong behaviours, or simply be gamed.</p>
<p>The Valcr Score was designed with that danger front of mind. Here's exactly how it's constructed — and why.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-score-is">What the score is<a href="https://docs.valcr.site/blog/how-valcr-score-works#what-the-score-is" class="hash-link" aria-label="Direct link to What the score is" title="Direct link to What the score is" translate="no">​</a></h2>
<p>The Valcr Score is a 0–100 composite that summarises a merchant's financial performance relative to their peer group in five dimensions. It is <strong>not</strong> an absolute measure of business quality. It is a relative measure — a percentile-anchored position within a defined comparison group.</p>
<p>A score of 74 means: across these five dimensions, this merchant outperforms approximately 74% of comparable businesses in the same category and segment.</p>
<p>That framing matters. A score of 74 for a $500K/year fashion DTC brand and a score of 74 for a $10M/year marketplace operator are not comparable — but both say something precise about where each business sits within its actual peer group.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-five-components">The five components<a href="https://docs.valcr.site/blog/how-valcr-score-works#the-five-components" class="hash-link" aria-label="Direct link to The five components" title="Direct link to The five components" translate="no">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Valcr Score = weighted average of 5 component scores</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Revenue Quality          25%</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Margin Health            25%</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Growth Trajectory        20%</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Customer Economics       20%</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">Operational Efficiency   10%</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="revenue-quality-25">Revenue Quality (25%)<a href="https://docs.valcr.site/blog/how-valcr-score-works#revenue-quality-25" class="hash-link" aria-label="Direct link to Revenue Quality (25%)" title="Direct link to Revenue Quality (25%)" translate="no">​</a></h3>
<p>Evaluates the composition and reliability of the revenue base:</p>
<ul>
<li class="">Recurring revenue share (subscription, membership, replenishment)</li>
<li class="">Channel concentration risk (overdependence on a single platform)</li>
<li class="">Net revenue retention where applicable</li>
<li class="">Revenue consistency across the trailing period</li>
</ul>
<p>A business with 60% direct-channel revenue, 20% Amazon, and meaningful subscription revenue scores higher on revenue quality than one that is 90% Amazon with no recurring component — even if the gross numbers are identical. The former is more defensible.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="margin-health-25">Margin Health (25%)<a href="https://docs.valcr.site/blog/how-valcr-score-works#margin-health-25" class="hash-link" aria-label="Direct link to Margin Health (25%)" title="Direct link to Margin Health (25%)" translate="no">​</a></h3>
<p>Gross margin percentile within peer group, adjusted for category norms. A 35% gross margin means something very different for an electronics seller (above median) than for a beauty brand (well below median). VCFS normalisation ensures these comparisons are valid.</p>
<p>Operating margin and net margin contribute when the data is available with sufficient confidence score (≥ 0.7 on the VCFS completeness scale).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="growth-trajectory-20">Growth Trajectory (20%)<a href="https://docs.valcr.site/blog/how-valcr-score-works#growth-trajectory-20" class="hash-link" aria-label="Direct link to Growth Trajectory (20%)" title="Direct link to Growth Trajectory (20%)" translate="no">​</a></h3>
<p>Revenue growth rate (QoQ and YoY) benchmarked against category peers. A 15% YoQ growth rate might be strong for a mature retail category and weak for an early-stage DTC brand growing in a fast-moving segment. The benchmark distribution makes this contextual.</p>
<p>Unit growth (order volume, SKU count expansion) is incorporated where available as a leading indicator when revenue growth lags.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="customer-economics-20">Customer Economics (20%)<a href="https://docs.valcr.site/blog/how-valcr-score-works#customer-economics-20" class="hash-link" aria-label="Direct link to Customer Economics (20%)" title="Direct link to Customer Economics (20%)" translate="no">​</a></h3>
<p>The most predictive component for long-term business health:</p>
<ul>
<li class="">LTV<!-- -->:CAC<!-- --> ratio percentile — the ratio of lifetime value to acquisition cost, benchmarked within segment</li>
<li class="">Repeat purchase rate vs. peer median</li>
<li class="">Cart abandonment rate (inverted — lower is better)</li>
<li class="">Average order value trend</li>
</ul>
<p>A business with a 6:1 LTV<!-- -->:CAC<!-- --> ratio, a 42% repeat purchase rate, and declining cart abandonment scores very well on this component regardless of where it sits on revenue or margin.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="operational-efficiency-10">Operational Efficiency (10%)<a href="https://docs.valcr.site/blog/how-valcr-score-works#operational-efficiency-10" class="hash-link" aria-label="Direct link to Operational Efficiency (10%)" title="Direct link to Operational Efficiency (10%)" translate="no">​</a></h3>
<p>Fulfilment quality and return economics:</p>
<ul>
<li class="">Refund/return rate percentile (inverted)</li>
<li class="">Fulfilment rate (orders delivered on time)</li>
<li class="">Average delivery time vs. category benchmark</li>
</ul>
<p>Weighted at 10% because operational metrics are often outside the merchant's direct control (carrier-dependent, geography-dependent) and are more volatile quarter-to-quarter.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="grade-bands">Grade bands<a href="https://docs.valcr.site/blog/how-valcr-score-works#grade-bands" class="hash-link" aria-label="Direct link to Grade bands" title="Direct link to Grade bands" translate="no">​</a></h2>
<table><thead><tr><th>Score</th><th>Grade</th><th>Interpretation</th></tr></thead><tbody><tr><td>90–100</td><td>A+</td><td>Top decile — exceptional relative to peers</td></tr><tr><td>80–89</td><td>A</td><td>Strong across all dimensions</td></tr><tr><td>70–79</td><td>B+</td><td>Above median, meaningful strengths</td></tr><tr><td>60–69</td><td>B</td><td>Solid fundamentals, clear improvement areas</td></tr><tr><td>50–59</td><td>C+</td><td>Mixed profile — some strengths, some gaps</td></tr><tr><td>40–49</td><td>C</td><td>Below median in multiple dimensions</td></tr><tr><td>Below 40</td><td>D</td><td>Significant underperformance vs. peers</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is-not">What it is not<a href="https://docs.valcr.site/blog/how-valcr-score-works#what-it-is-not" class="hash-link" aria-label="Direct link to What it is not" title="Direct link to What it is not" translate="no">​</a></h2>
<p>The Valcr Score is not a credit score. It does not incorporate repayment history, days outstanding, or liability structure. Lenders using Valcr data for underwriting combine the score with their own credit assessment — the score provides peer-relative financial context that their models typically lack, not a complete credit decision.</p>
<p>The score is not static. It is recalculated each time a new VCFS submission is processed, and the benchmark pool it draws from is updated quarterly. A score from six months ago reflects the merchant's position at that time relative to the peer group as it was constituted then.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="accessing-the-score">Accessing the score<a href="https://docs.valcr.site/blog/how-valcr-score-works#accessing-the-score" class="hash-link" aria-label="Direct link to Accessing the score" title="Direct link to Accessing the score" translate="no">​</a></h2>
<p>The Valcr Score is available on Enterprise plans via the <a class="" href="https://docs.valcr.site/api/merchant#get-merchantscore"><code>GET /merchant/score</code></a> endpoint. It requires a VCFS completeness score of at least 0.70 to compute reliably.</p>
<p>The response includes not just the composite score but the individual component scores, the peer percentile rank, and the quarter-over-quarter trend — so the number is always accompanied by enough context to be genuinely useful.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"valcr_score"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">74</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"grade"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"B+"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"components"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"revenue_quality"</span><span class="token operator">:</span><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"score"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">81</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"weight"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.25</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"margin_health"</span><span class="token operator">:</span><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"score"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">76</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"weight"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.25</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"growth_trajectory"</span><span class="token operator">:</span><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"score"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">68</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"weight"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.20</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"customer_economics"</span><span class="token operator">:</span><span class="token plain">     </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"score"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">71</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"weight"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.20</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"operational_efficiency"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"score"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">62</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"weight"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0.10</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"peer_percentile"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">68.2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"trend"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"prev_score"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">70</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"delta"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">4</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"direction"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"up"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<hr>
<p><a class="" href="https://docs.valcr.site/api/merchant#get-merchantscore">See the full score endpoint documentation →</a></p>]]></content:encoded>
            <category>valcr-score</category>
            <category>benchmarks</category>
            <category>underwriting</category>
            <category>product</category>
        </item>
        <item>
            <title><![CDATA[How Valcr API Keys Are Secured]]></title>
            <link>https://docs.valcr.site/blog/api-key-security-model</link>
            <guid>https://docs.valcr.site/blog/api-key-security-model</guid>
            <pubDate>Tue, 10 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[How Valcr API keys are generated, stored, and validated securely: SHA-256 hashing, 287-bit entropy, rotation design, and production security practices.]]></description>
            <content:encoded><![CDATA[<p>API key security is one of those topics where the difference between "good enough" and "actually secure" is invisible until something goes wrong. This post explains exactly how Valcr API keys are designed, stored, and validated — and the reasoning behind each decision.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="key-generation">Key generation<a href="https://docs.valcr.site/blog/api-key-security-model#key-generation" class="hash-link" aria-label="Direct link to Key generation" title="Direct link to Key generation" translate="no">​</a></h2>
<p>Every Valcr API key is generated using Python's <code>secrets.token_urlsafe(36)</code> — a cryptographically secure random string drawing from <code>/dev/urandom</code>, producing 48 characters of URL-safe base64 encoding from 36 bytes of randomness.</p>
<p>That gives each key approximately <strong>287 bits of effective entropy</strong>. For context, the absolute minimum considered adequate for API keys is 128 bits. 287 bits makes brute-force enumeration computationally infeasible for any foreseeable future.</p>
<p>Keys are prefixed with the environment:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">vcr_live_xKj9RzMnP4qBvWsY...  ← production</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">vcr_test_aB2cDeFgHiJkLmNo...  ← sandbox</span><br></div></code></pre></div></div>
<p>The prefix serves a practical purpose: it makes keys identifiable in logs, in code review, and in leaked credential scanning tools (similar to how GitHub tokens begin <code>ghp_</code> and Stripe keys begin <code>sk_live_</code>). GitHub's secret scanning automatically flags patterns like these before they reach production.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-we-store--and-what-we-dont">What we store — and what we don't<a href="https://docs.valcr.site/blog/api-key-security-model#what-we-store--and-what-we-dont" class="hash-link" aria-label="Direct link to What we store — and what we don't" title="Direct link to What we store — and what we don't" translate="no">​</a></h2>
<p>This is the critical decision. When you create an API key in the Valcr Console, the sequence is:</p>
<ol>
<li class=""><code>raw_key = f"vcr_{env}_{secrets.token_urlsafe(36)}"</code></li>
<li class=""><code>key_hash = hashlib.sha256(raw_key.encode()).hexdigest()</code></li>
<li class="">Store <code>key_hash</code> in the database</li>
<li class="">Return <code>raw_key</code> in the API response — <strong>once, immediately</strong></li>
<li class="">Discard <code>raw_key</code> from memory</li>
</ol>
<p>We store the SHA-256 hash. We never store the raw key. After the creation response is returned, <strong>no system at Valcr holds the raw value</strong> — not the database, not logs, not application memory.</p>
<p>The consequence is intentional: if our database were completely compromised, the attacker gets a list of SHA-256 hashes with no practical path to recovering the raw keys. A 287-bit random value is not susceptible to rainbow table attacks or dictionary attacks.</p>
<p>The user consequence is also intentional: if you lose the key, it must be rotated. There is no "show me my key again" feature because there is no copy to show.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-sha-256-and-not-bcrypt">Why SHA-256 and not bcrypt?<a href="https://docs.valcr.site/blog/api-key-security-model#why-sha-256-and-not-bcrypt" class="hash-link" aria-label="Direct link to Why SHA-256 and not bcrypt?" title="Direct link to Why SHA-256 and not bcrypt?" translate="no">​</a></h3>
<p>bcrypt is the right choice for passwords because passwords have low entropy — humans choose predictable strings from a limited character set, which makes offline dictionary attacks viable against unsalted or weakly salted hashes.</p>
<p>API keys with 287 bits of entropy are not susceptible to dictionary attacks. The computation overhead of bcrypt on every API request (which requires a hash lookup on every authenticated call) introduces unnecessary latency with no security benefit. SHA-256 lookup in an indexed database column is fast, correct, and appropriate.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="validation-on-every-request">Validation on every request<a href="https://docs.valcr.site/blog/api-key-security-model#validation-on-every-request" class="hash-link" aria-label="Direct link to Validation on every request" title="Direct link to Validation on every request" translate="no">​</a></h2>
<p>Every authenticated request to the Data API runs this sequence:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">1. Extract token from Authorization: Bearer &lt;token&gt;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">2. Compute SHA-256(token)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">3. SELECT * FROM api_keys WHERE key_hash = $1 AND is_active = true</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">4. Check: key.environment matches request target</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">5. Check: required_scope ∈ key.scopes</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">6. Check: rate limit (per key, sliding window)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">7. Check: account quota (per billing period)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">8. Forward to handler</span><br></div></code></pre></div></div>
<p>Steps 4–7 all happen before the request reaches any business logic. A request that fails any check never touches the data layer.</p>
<p>The hash lookup uses a database index on <code>key_hash</code>. Combined with the fixed-length output of SHA-256 (64 hex characters), this is a single indexed equality scan — consistently fast regardless of dataset size.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="scope-enforcement">Scope enforcement<a href="https://docs.valcr.site/blog/api-key-security-model#scope-enforcement" class="hash-link" aria-label="Direct link to Scope enforcement" title="Direct link to Scope enforcement" translate="no">​</a></h2>
<p>Scopes follow the pattern <code>resource:action</code> and are stored as an array on the key record. The endpoint-to-scope mapping is maintained in the application layer:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">ENDPOINT_SCOPE_MAP </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"GET /benchmarks"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">              </span><span class="token string" style="color:rgb(255, 121, 198)">"benchmarks:read"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"GET /benchmarks/percentile"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">   </span><span class="token string" style="color:rgb(255, 121, 198)">"benchmarks:read"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"GET /segments"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"segments:read"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"GET /merchant/vcfs"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">           </span><span class="token string" style="color:rgb(255, 121, 198)">"merchant:read"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"POST /merchant/vcfs"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">          </span><span class="token string" style="color:rgb(255, 121, 198)">"merchant:write"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"GET /merchant/insights"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">       </span><span class="token string" style="color:rgb(255, 121, 198)">"insights:read"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"GET /merchant/score"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">          </span><span class="token string" style="color:rgb(255, 121, 198)">"score:read"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"GET /export/xbrl"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">             </span><span class="token string" style="color:rgb(255, 121, 198)">"export:read"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>If the scope is not present on the key, the request returns <code>403 Forbidden</code> — not <code>401 Unauthorized</code>. This distinction is deliberate: <code>401</code> means "not authenticated," <code>403</code> means "authenticated but not permitted." The difference helps integration developers understand whether they have a key problem or a scope problem.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="key-rotation">Key rotation<a href="https://docs.valcr.site/blog/api-key-security-model#key-rotation" class="hash-link" aria-label="Direct link to Key rotation" title="Direct link to Key rotation" translate="no">​</a></h2>
<p>Rotation is the recommended response to any suspected key exposure — or simply as a regular security hygiene practice (every 90 days is reasonable for production integrations).</p>
<p>When a key is rotated:</p>
<ol>
<li class="">A new raw key is generated with the same process as creation</li>
<li class="">The <code>key_hash</code> column on the existing record is overwritten atomically with the new hash</li>
<li class="">The old hash is gone — immediately invalid</li>
<li class="">The new raw key is returned in the rotation response — once</li>
</ol>
<p>The atomic overwrite means there is no window where both the old and new key are simultaneously valid. The trade-off is that any in-flight requests using the old key at the moment of rotation will fail. For production systems where this matters, coordinate rotations with a low-traffic window or implement a brief retry on <code>401</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-means-for-your-integration">What this means for your integration<a href="https://docs.valcr.site/blog/api-key-security-model#what-this-means-for-your-integration" class="hash-link" aria-label="Direct link to What this means for your integration" title="Direct link to What this means for your integration" translate="no">​</a></h2>
<p>A few practical implications:</p>
<p><strong>Store keys in environment variables, never in code.</strong> A key committed to a git repository is compromised — even if the repo is private, even if you delete the commit. Environment variables keep credentials out of version control entirely.</p>
<p><strong>Use test keys during development.</strong> Test keys (<code>vcr_test_*</code>) return seeded data and never count against your quota or trigger billing. There is no reason to use a live key in a development or CI environment.</p>
<p><strong>Assign minimum required scopes.</strong> If your integration only reads benchmarks, create a key with only <code>benchmarks:read</code>. A compromised key with minimal scopes has minimal blast radius.</p>
<p><strong>Rotate if in doubt.</strong> Rotation takes 30 seconds in the Console. If a key was ever logged, ever appeared in an error message, ever shipped in a build artifact — rotate it. The old key is invalidated immediately.</p>
<hr>
<p><a class="" href="https://docs.valcr.site/auth">Read the full authentication documentation →</a></p>]]></content:encoded>
            <category>security</category>
            <category>api</category>
            <category>engineering</category>
            <category>authentication</category>
        </item>
        <item>
            <title><![CDATA[Ecommerce Gross Margin Benchmarks: 2024 Q4 Data]]></title>
            <link>https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024</link>
            <guid>https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024</guid>
            <pubDate>Tue, 03 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Q4 2024 ecommerce gross margin benchmarks by segment: Beauty at 61% median, Electronics at 28%. Full p25/p50/p75/p90 distributions from the Valcr dataset.]]></description>
            <content:encoded><![CDATA[<p>Gross margin is the first number any serious financial analysis of an ecommerce business reaches for. It tells you whether the unit economics are structurally viable before operating costs enter the picture.</p>
<p>Here is what the Q4 2024 Valcr benchmark data shows across categories — and more importantly, what the distributions reveal that headline averages hide.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-data">The data<a href="https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024#the-data" class="hash-link" aria-label="Direct link to The data" title="Direct link to The data" translate="no">​</a></h2>
<p>Q4 2024 benchmark pool: <strong>8,420 ecommerce merchants</strong> across seven sub-segments, with VCFS completeness scores of ≥ 0.50 (sufficient confidence for margin benchmarking).</p>
<p>All gross margin figures use the VCFS definition: <code>(net_revenue - COGS) / net_revenue</code>, where COGS excludes fulfilment and shipping unless it is a direct cost of the physical product.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="by-sub-segment">By sub-segment<a href="https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024#by-sub-segment" class="hash-link" aria-label="Direct link to By sub-segment" title="Direct link to By sub-segment" translate="no">​</a></h3>
<table><thead><tr><th>Segment</th><th>p25</th><th>p50</th><th>p75</th><th>p90</th><th>Sample</th></tr></thead><tbody><tr><td>Beauty &amp; Personal Care</td><td>0.44</td><td>0.61</td><td>0.72</td><td>0.81</td><td>980</td></tr><tr><td>Health &amp; Wellness</td><td>0.38</td><td>0.54</td><td>0.66</td><td>0.76</td><td>970</td></tr><tr><td>Fashion &amp; Apparel</td><td>0.31</td><td>0.44</td><td>0.59</td><td>0.68</td><td>1,842</td></tr><tr><td>Pets</td><td>0.29</td><td>0.42</td><td>0.55</td><td>0.64</td><td>390</td></tr><tr><td>Sports &amp; Outdoors</td><td>0.26</td><td>0.41</td><td>0.54</td><td>0.63</td><td>640</td></tr><tr><td>Home &amp; Garden</td><td>0.22</td><td>0.38</td><td>0.51</td><td>0.61</td><td>870</td></tr><tr><td>Food &amp; Beverage</td><td>0.19</td><td>0.35</td><td>0.48</td><td>0.58</td><td>580</td></tr><tr><td>Electronics &amp; Tech</td><td>0.14</td><td>0.28</td><td>0.41</td><td>0.52</td><td>1,120</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-distribution-reveals">What the distribution reveals<a href="https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024#what-the-distribution-reveals" class="hash-link" aria-label="Direct link to What the distribution reveals" title="Direct link to What the distribution reveals" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-spread-is-the-story">The spread is the story<a href="https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024#the-spread-is-the-story" class="hash-link" aria-label="Direct link to The spread is the story" title="Direct link to The spread is the story" translate="no">​</a></h3>
<p>The median is useful context. The distribution is where the real information lives.</p>
<p>Take fashion and apparel: the median is 44%, but the p25 is 31% and the p90 is 68%. That is a 37-point spread between the bottom quarter and the top 10% of the segment. A fashion brand at 44% is not doing well — it is average. A fashion brand at 62% is genuinely exceptional and likely has a structural advantage (direct-to-consumer with minimal marketplace dependency, owned manufacturing, or premium positioning with pricing power).</p>
<p>For underwriters: a fashion brand presenting a 31% gross margin is at the 25th percentile. Not a red flag on its own — a quarter of the segment sits there — but it warrants understanding <em>why</em>. Is it channel mix (heavy Amazon dependency eroding margin through fees)? Product category within fashion (accessories vs. basics)? Season-specific COGS inflation?</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="beautys-structural-advantage">Beauty's structural advantage<a href="https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024#beautys-structural-advantage" class="hash-link" aria-label="Direct link to Beauty's structural advantage" title="Direct link to Beauty's structural advantage" translate="no">​</a></h3>
<p>Beauty and personal care's 61% median is not an accident. The category benefits from:</p>
<ul>
<li class=""><strong>High perceived value at low material cost</strong> — a $40 serum with $4 of formulation is structurally different from a $40 electronics accessory that cost $28 to manufacture</li>
<li class=""><strong>Direct channel dominance</strong> — beauty has the highest own-website share of any ecommerce category in the Valcr dataset (64% median vs. 41% for fashion and 28% for electronics)</li>
<li class=""><strong>Replenishment economics</strong> — products that run out create recurring revenue without the acquisition cost overhead that compresses margin in single-purchase categories</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="electronics-structural-compression">Electronics' structural compression<a href="https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024#electronics-structural-compression" class="hash-link" aria-label="Direct link to Electronics' structural compression" title="Direct link to Electronics' structural compression" translate="no">​</a></h3>
<p>Electronics trails every category at 28% median. The reasons are well understood but worth stating precisely:</p>
<ul>
<li class=""><strong>Commodity component pricing</strong> — electronics COGS is high relative to retail price, and component costs are transparent (competitive reference pricing exists for almost every component)</li>
<li class=""><strong>Marketplace dependency</strong> — electronics has the highest Amazon revenue share in the dataset (median 44% of revenue through Amazon), and Amazon's referral fees (6–8% for electronics) directly compress margin before operating costs</li>
<li class=""><strong>Price comparison pressure</strong> — price comparison tools make premium positioning structurally difficult; most SKUs trade at near-identical prices across platforms</li>
</ul>
<p>A well-run electronics operation at 41% gross margin (p75) has likely achieved either category specialisation (professional/B2B equipment with lower competition and lower price comparison pressure) or meaningful private-label positioning.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quarter-over-quarter-trend">Quarter-over-quarter trend<a href="https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024#quarter-over-quarter-trend" class="hash-link" aria-label="Direct link to Quarter-over-quarter trend" title="Direct link to Quarter-over-quarter trend" translate="no">​</a></h2>
<p>Comparing Q3 2024 to Q4 2024 across the full ecommerce pool:</p>
<table><thead><tr><th>Metric</th><th>Q3 2024</th><th>Q4 2024</th><th>Δ</th></tr></thead><tbody><tr><td>Median gross margin</td><td>0.42</td><td>0.43</td><td>+1pp</td></tr><tr><td>p75 gross margin</td><td>0.57</td><td>0.58</td><td>+1pp</td></tr><tr><td>p25 gross margin</td><td>0.29</td><td>0.30</td><td>+1pp</td></tr></tbody></table>
<p>The 1pp uplift at all percentiles in Q4 reflects two things: seasonal pricing power (premium pricing during peak gifting season) and sample composition shift (Q4 skews toward fashion and beauty in the dataset as Amazon sellers activate holiday inventory).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="using-the-api">Using the API<a href="https://docs.valcr.site/blog/ecommerce-gross-margin-benchmarks-2024#using-the-api" class="hash-link" aria-label="Direct link to Using the API" title="Direct link to Using the API" translate="no">​</a></h2>
<p>All of this data is available programmatically via the Valcr Data API:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> requests</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">r </span><span class="token operator">=</span><span class="token plain"> requests</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"https://api.valcr.site/data/v1/benchmarks"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    headers</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"Authorization"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Bearer vcr_live_your_key"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    params</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"category"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ecommerce"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"segment"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"fashion"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"period"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2024-Q4"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">data </span><span class="token operator">=</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">gm </span><span class="token operator">=</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"metrics"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"gross_margin"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"p50: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">gm</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'p50'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation format-spec">.1%</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">  p75: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">gm</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'p75'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation format-spec">.1%</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">  p90: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">gm</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'p90'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation format-spec">.1%</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># → p50: 44.0%  p75: 59.0%  p90: 68.0%</span><br></div></code></pre></div></div>
<p>To rank a specific merchant's gross margin against the distribution:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">r </span><span class="token operator">=</span><span class="token plain"> requests</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"https://api.valcr.site/data/v1/benchmarks/percentile"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    headers</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"Authorization"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Bearer vcr_live_your_key"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    params</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"metric"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"gross_margin"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">0.52</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"category"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ecommerce"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"segment"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"fashion"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">result </span><span class="token operator">=</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">result</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'percentile'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation format-spec">.0f</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">th percentile"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># → 71st percentile</span><br></div></code></pre></div></div>
<hr>
<p><a class="" href="https://docs.valcr.site/api/benchmarks">Access the benchmarks API →</a> · <a href="https://console.valcr.site/" target="_blank" rel="noopener noreferrer" class="">Get a free Console account →</a></p>
<p><em>Data from the Valcr benchmark pool, Q4 2024. N=8,420. All figures use VCFS-normalised calculation methodology.</em></p>]]></content:encoded>
            <category>benchmarks</category>
            <category>data</category>
            <category>gross-margin</category>
            <category>ecommerce</category>
        </item>
        <item>
            <title><![CDATA[How to Embed Commerce Benchmarks in Your SaaS Product]]></title>
            <link>https://docs.valcr.site/blog/embedding-benchmarks-in-your-saas</link>
            <guid>https://docs.valcr.site/blog/embedding-benchmarks-in-your-saas</guid>
            <pubDate>Tue, 26 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[How to integrate Valcr benchmark data into your SaaS product: Python and TypeScript integration patterns, caching strategy, and UI implementation guide.]]></description>
            <content:encoded><![CDATA[<p>One of the most common features that ecommerce SaaS products get asked for — and one of the hardest to build well — is benchmarking. "How do my metrics compare to other businesses like mine?"</p>
<p>It's a simple question. Building an answer to it is not. You need a dataset of comparable businesses, a consistent normalisation methodology, regular updates, and enough sample depth per segment to produce credible distributions. Most SaaS companies decide the build cost isn't worth it and ship a chart with industry averages from a three-year-old report instead.</p>
<p>The Valcr API exists specifically to solve this. Here's how to integrate it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-integration-pattern">The integration pattern<a href="https://docs.valcr.site/blog/embedding-benchmarks-in-your-saas#the-integration-pattern" class="hash-link" aria-label="Direct link to The integration pattern" title="Direct link to The integration pattern" translate="no">​</a></h2>
<p>The core pattern is straightforward:</p>
<ol>
<li class="">Your user's financial data lives in your platform (or you calculate it from transactions)</li>
<li class="">You call the Valcr API to get the benchmark distribution for their category and metric</li>
<li class="">You call the percentile endpoint to rank their specific value</li>
<li class="">You render the result — a chart, a badge, a scorecard, whatever fits your UI</li>
</ol>
<p>You don't need to move user data to Valcr's servers unless you want to use the VCFS profile features. The benchmark endpoints are read-only lookups against the Valcr dataset — you bring the merchant's metric, Valcr tells you where it sits.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1-create-a-server-side-api-key">Step 1: Create a server-side API key<a href="https://docs.valcr.site/blog/embedding-benchmarks-in-your-saas#step-1-create-a-server-side-api-key" class="hash-link" aria-label="Direct link to Step 1: Create a server-side API key" title="Direct link to Step 1: Create a server-side API key" translate="no">​</a></h2>
<p>Create a key with <code>benchmarks:read</code> and <code>segments:read</code> scopes in the <a href="https://console.valcr.site/" target="_blank" rel="noopener noreferrer" class="">Console</a>. Store it as an environment variable on your backend. Never expose it client-side.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">VALCR_API_KEY</span><span class="token operator">=</span><span class="token plain">vcr_live_your_key_here</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2-build-a-benchmark-lookup-function">Step 2: Build a benchmark lookup function<a href="https://docs.valcr.site/blog/embedding-benchmarks-in-your-saas#step-2-build-a-benchmark-lookup-function" class="hash-link" aria-label="Direct link to Step 2: Build a benchmark lookup function" title="Direct link to Step 2: Build a benchmark lookup function" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Python / FastAPI backend</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> os</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> requests</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> functools </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> lru_cache</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">VALCR_BASE </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://api.valcr.site/data/v1"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">VALCR_KEY  </span><span class="token operator">=</span><span class="token plain"> os</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">environ</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"VALCR_API_KEY"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">HEADERS    </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"Authorization"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Bearer </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">VALCR_KEY</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">@lru_cache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">maxsize</span><span class="token operator">=</span><span class="token number">128</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">get_benchmark_distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">category</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> period</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Cache benchmark distributions — they update quarterly, not per-request."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    params </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"category"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> category</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"metric"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> period</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"period"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> period</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    r </span><span class="token operator">=</span><span class="token plain"> requests</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">VALCR_BASE</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">/benchmarks"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> headers</span><span class="token operator">=</span><span class="token plain">HEADERS</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> params</span><span class="token operator">=</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">raise_for_status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"metrics"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">get_merchant_percentile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">category</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">float</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    r </span><span class="token operator">=</span><span class="token plain"> requests</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">VALCR_BASE</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">/benchmarks/percentile"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        headers</span><span class="token operator">=</span><span class="token plain">HEADERS</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        params</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"category"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> category</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"metric"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">raise_for_status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Usage in your route handler:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">@app</span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/api/merchant/{merchant_id}/benchmark"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">merchant_benchmark</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">merchant_id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"gross_margin"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    merchant </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> db</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get_merchant</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">merchant_id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    merchant_value </span><span class="token operator">=</span><span class="token plain"> merchant</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">calculate_metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># your own calculation</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    distribution </span><span class="token operator">=</span><span class="token plain"> get_benchmark_distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">merchant</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">category</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    rank </span><span class="token operator">=</span><span class="token plain"> get_merchant_percentile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">merchant</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">category</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> merchant_value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"metric"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">        metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"merchant_value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> merchant_value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"percentile"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">    rank</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"percentile"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"distribution"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">  distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"interpretation"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> rank</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"interpretation"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// TypeScript / Next.js API route</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">VALCR_BASE</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://api.valcr.site/data/v1"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">HEADERS</span><span class="token plain">    </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token maybe-class-name">Authorization</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">Bearer </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">process</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation property-access">env</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation constant" style="color:rgb(189, 147, 249)">VALCR_API_KEY</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Cache with a simple in-memory map — distributions update quarterly</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> distributionCache </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name known-class-name class-name">Map</span><span class="token class-name operator">&lt;</span><span class="token class-name builtin" style="color:rgb(189, 147, 249)">string</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token class-name"> </span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token class-name"> data</span><span class="token class-name operator">:</span><span class="token class-name"> </span><span class="token class-name builtin" style="color:rgb(189, 147, 249)">any</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token class-name"> ts</span><span class="token class-name operator">:</span><span class="token class-name"> </span><span class="token class-name builtin" style="color:rgb(189, 147, 249)">number</span><span class="token class-name"> </span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token class-name operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">CACHE_TTL</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">6</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">60</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">60</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">1000</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// 6 hours</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">getBenchmarkDistribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">category</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> metric</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> key </span><span class="token operator">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">category</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">:</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">metric</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> cached </span><span class="token operator">=</span><span class="token plain"> distributionCache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cached </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token known-class-name class-name">Date</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">now</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> cached</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ts</span><span class="token plain"> </span><span class="token operator">&lt;</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">CACHE_TTL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cached</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">data</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> res </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">fetch</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation constant" style="color:rgb(189, 147, 249)">VALCR_BASE</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">/benchmarks?category=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">category</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">HEADERS</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> data </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> dist </span><span class="token operator">=</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">metrics</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  distributionCache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> data</span><span class="token operator">:</span><span class="token plain"> dist</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ts</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Date</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">now</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> dist</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">GET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">req</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> searchParams </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name constant" style="color:rgb(189, 147, 249)">URL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> category </span><span class="token operator">=</span><span class="token plain"> searchParams</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"category"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ecommerce"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> metric   </span><span class="token operator">=</span><span class="token plain"> searchParams</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"metric"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">   </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"gross_margin"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> value    </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">parseFloat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">searchParams</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> rank</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token known-class-name class-name">Promise</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">all</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">getBenchmarkDistribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">category</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">fetch</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation constant" style="color:rgb(189, 147, 249)">VALCR_BASE</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">/benchmarks/percentile?category=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">category</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">&amp;metric=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">metric</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">&amp;value=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">value</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">HEADERS</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">then</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r </span><span class="token arrow operator">=&gt;</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">Response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> rank </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3-cache-aggressively">Step 3: Cache aggressively<a href="https://docs.valcr.site/blog/embedding-benchmarks-in-your-saas#step-3-cache-aggressively" class="hash-link" aria-label="Direct link to Step 3: Cache aggressively" title="Direct link to Step 3: Cache aggressively" translate="no">​</a></h2>
<p>Benchmark distributions update quarterly. Hitting the Valcr API on every page load for benchmark data is wasteful and unnecessary. Cache at the application layer:</p>
<ul>
<li class=""><strong>Distribution data</strong> (<code>/benchmarks</code>) — cache for 6–24 hours. The data doesn't change intra-day.</li>
<li class=""><strong>Percentile lookups</strong> (<code>/benchmarks/percentile</code>) — cache per merchant, per metric, per period. Recalculate when the merchant's own metrics update.</li>
<li class=""><strong>Segment lists</strong> (<code>/segments</code>) — cache for 24+ hours. New segments are added quarterly.</li>
</ul>
<p>This also means your Valcr API quota goes almost entirely to percentile lookups (one per merchant metric update) rather than distribution fetches — making the economics of embedding benchmarks very favourable even at Developer tier.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-4-design-the-ui">Step 4: Design the UI<a href="https://docs.valcr.site/blog/embedding-benchmarks-in-your-saas#step-4-design-the-ui" class="hash-link" aria-label="Direct link to Step 4: Design the UI" title="Direct link to Step 4: Design the UI" translate="no">​</a></h2>
<p>The most effective benchmark visualisations are not pie charts. They are distribution charts with the merchant's position marked — showing where they sit, who they're near, and what the top quartile looks like.</p>
<p>A minimal implementation:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// React component — benchmark position visualiser</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">BenchmarkBar</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> metric</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> merchantValue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> distribution </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(80, 250, 123)">pct</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">v</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">number</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string interpolation">v </span><span class="token template-string interpolation operator">*</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation number">100</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation function" style="color:rgb(80, 250, 123)">toFixed</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string interpolation number">0</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">%</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> merchantPct </span><span class="token operator">=</span><span class="token plain"> distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">p50</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">?</span><span class="token plain"> </span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">min</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">round</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">merchantValue </span><span class="token operator">/</span><span class="token plain"> distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">p90</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">90</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">100</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">50</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">benchmark-bar</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">bar-track</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">bar-zone p25-p75</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">style</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">          left</span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">  </span><span class="token tag script language-javascript function" style="color:rgb(80, 250, 123)">pct</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">distribution</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">p25</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">/</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> distribution</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">p90</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">          width</span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript function" style="color:rgb(80, 250, 123)">pct</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">distribution</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">p75</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">-</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> distribution</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">p25</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">/</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> distribution</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">p90</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">        </span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">/&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">bar-median</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">style</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> left</span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript function" style="color:rgb(80, 250, 123)">pct</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">distribution</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">p50</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">/</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> distribution</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">p90</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">/&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">bar-merchant</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">style</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> left</span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token tag script language-javascript template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token tag script language-javascript template-string interpolation" style="color:rgb(255, 121, 198)">merchantPct</span><span class="token tag script language-javascript template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag script language-javascript template-string string" style="color:rgb(255, 121, 198)">%</span><span class="token tag script language-javascript template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">          </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">merchant-label</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token function" style="color:rgb(80, 250, 123)">pct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">merchantValue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">bar-labels</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">p25: </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token function" style="color:rgb(80, 250, 123)">pct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">p25</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">Median: </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token function" style="color:rgb(80, 250, 123)">pct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">p50</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">p75: </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token function" style="color:rgb(80, 250, 123)">pct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">distribution</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">p75</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>The middle 50% (p25–p75) shaded, the median marked, the merchant's position as a pin. Users immediately understand where they sit without needing to read a number.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-dont-need-to-build">What you don't need to build<a href="https://docs.valcr.site/blog/embedding-benchmarks-in-your-saas#what-you-dont-need-to-build" class="hash-link" aria-label="Direct link to What you don't need to build" title="Direct link to What you don't need to build" translate="no">​</a></h2>
<p>Using the Valcr API for benchmarking means you don't have to:</p>
<ul>
<li class="">Recruit a benchmark panel of comparable businesses</li>
<li class="">Design and maintain a data normalisation pipeline</li>
<li class="">Decide how to handle outliers and sample size minimums</li>
<li class="">Update the data every quarter</li>
<li class="">Handle the methodology questions that users inevitably ask ("how was this calculated?")</li>
</ul>
<p>The methodology is documented in the <a class="" href="https://docs.valcr.site/guides/vcfs-schema">VCFS schema guide</a> and <a class="" href="https://docs.valcr.site/api/benchmarks">benchmark API reference</a>. Your users can read it. You didn't have to write it.</p>
<hr>
<p><a class="" href="https://docs.valcr.site/quickstart">Start with the Quickstart →</a> · <a class="" href="https://docs.valcr.site/auth#scopes">API key scopes reference →</a></p>]]></content:encoded>
            <category>api</category>
            <category>developers</category>
            <category>saas</category>
            <category>integration</category>
            <category>product</category>
        </item>
        <item>
            <title><![CDATA[LTV:CAC Benchmarks: What the Ratio Actually Means]]></title>
            <link>https://docs.valcr.site/blog/ltv-cac-ratio-benchmarks</link>
            <guid>https://docs.valcr.site/blog/ltv-cac-ratio-benchmarks</guid>
            <pubDate>Tue, 12 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[LTV:CAC ratio benchmarks by ecommerce category from Q4 2024 Valcr data. The 3:1 myth debunked — what the actual distributions show.]]></description>
            <content:encoded><![CDATA[<p>The "3:1 LTV<!-- -->:CAC<!-- --> is healthy" benchmark has been repeated in enough blog posts and pitch deck templates that it has taken on the quality of received wisdom. Raise a VC round and someone will compare your ratio to 3:1. Apply for revenue-based financing and the underwriter will check it.</p>
<p>The problem: that number didn't come from a distribution. It came from a SaaS heuristic from the early 2010s, applied to a subscription business model, and has since been cargo-culted onto every business model in the internet economy regardless of whether it makes sense.</p>
<p>Here is what the actual data shows.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="first-how-valcr-calculates-ltv">First: how Valcr calculates LTV<!-- -->:CAC<a href="https://docs.valcr.site/blog/ltv-cac-ratio-benchmarks#first-how-valcr-calculates-ltv" class="hash-link" aria-label="Direct link to first-how-valcr-calculates-ltv" title="Direct link to first-how-valcr-calculates-ltv" translate="no">​</a></h2>
<p>VCFS defines these fields precisely because imprecision makes the ratio meaningless:</p>
<p><strong>Customer LTV</strong> = projected net revenue from a customer over their lifetime with the business. Valcr uses a cohort-based calculation where available: <code>average_order_value × purchase_frequency × gross_margin × (1 / churn_rate)</code>. Where churn data is unavailable, a simplified version using trailing 12-month repeat purchase rates is used, with a confidence score adjustment applied to the benchmark.</p>
<p><strong>Customer Acquisition Cost</strong> = total marketing and sales spend in the period divided by new customers acquired. "Total" means all paid channels, all agency fees, all content production costs attributed to acquisition. Not just ad spend.</p>
<p>The ratio = <code>customer_ltv / customer_acquisition_cost</code>.</p>
<p>If your platform calculates these differently, your ratio is not comparable to the benchmark. This is not a criticism — it is a measurement problem that VCFS exists to solve.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-data-shows">What the data shows<a href="https://docs.valcr.site/blog/ltv-cac-ratio-benchmarks#what-the-data-shows" class="hash-link" aria-label="Direct link to What the data shows" title="Direct link to What the data shows" translate="no">​</a></h2>
<p>From the Q4 2024 Valcr dataset, LTV<!-- -->:CAC<!-- --> ratio by ecommerce category:</p>
<table><thead><tr><th>Segment</th><th>p25</th><th>p50</th><th>p75</th><th>p90</th><th>Notes</th></tr></thead><tbody><tr><td>Beauty &amp; Personal Care</td><td>3.8</td><td>6.2</td><td>9.4</td><td>14.1</td><td>Highest replenishment rates</td></tr><tr><td>Health &amp; Wellness</td><td>3.2</td><td>5.4</td><td>8.1</td><td>12.0</td><td>Subscription uplift in supplement sub-segment</td></tr><tr><td>Pet supplies</td><td>3.1</td><td>5.1</td><td>7.8</td><td>11.6</td><td>High repeat purchase frequency</td></tr><tr><td>Fashion &amp; Apparel</td><td>1.8</td><td>3.1</td><td>4.9</td><td>7.2</td><td>Wide variance; depends heavily on return rate</td></tr><tr><td>Home &amp; Garden</td><td>1.6</td><td>2.8</td><td>4.4</td><td>6.8</td><td>Lower purchase frequency compresses LTV</td></tr><tr><td>Electronics &amp; Tech</td><td>1.2</td><td>2.1</td><td>3.4</td><td>5.1</td><td>Low repeat rate; high per-unit value</td></tr><tr><td>Food &amp; Beverage</td><td>2.9</td><td>4.8</td><td>7.2</td><td>10.4</td><td>Consumable replenishment dominates</td></tr></tbody></table>
<p>The ecommerce-wide p50 is <strong>3.8:1</strong> — above the 3:1 baseline. But that aggregate masks enormous variation across categories.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-31-myth-in-context">The 3:1 myth in context<a href="https://docs.valcr.site/blog/ltv-cac-ratio-benchmarks#the-31-myth-in-context" class="hash-link" aria-label="Direct link to The 3:1 myth in context" title="Direct link to The 3:1 myth in context" translate="no">​</a></h2>
<p>A fashion brand with a 3.1:1 LTV<!-- -->:CAC<!-- --> ratio is at the <strong>median for its category</strong>. That is not great — it is average. A health &amp; wellness brand with a 3.1:1 ratio is in the <strong>bottom quartile</strong>. The same number means opposite things.</p>
<p>This is exactly why context-free benchmarks are dangerous. The 3:1 heuristic was derived from SaaS subscription businesses with predictable churn and no inventory. It has been applied as a universal standard to businesses where:</p>
<ul>
<li class="">Repeat purchase rates vary from 8% (one-time gift electronics) to 62% (pet food)</li>
<li class="">COGS varies from 18% (software subscription) to 72% (commodity electronics)</li>
<li class="">Customer lifecycle varies from 14 months (fast fashion) to 8+ years (premium pet supply)</li>
</ul>
<p>A 3:1 ratio for a consumables brand with 55% gross margin and 52% repeat purchase rate is a sign of a broken acquisition funnel. A 3:1 ratio for a premium furniture brand where customers buy once every five years is structurally reasonable.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-a-good-ratio-looks-like-by-model">What a good ratio looks like by model<a href="https://docs.valcr.site/blog/ltv-cac-ratio-benchmarks#what-a-good-ratio-looks-like-by-model" class="hash-link" aria-label="Direct link to What a good ratio looks like by model" title="Direct link to What a good ratio looks like by model" translate="no">​</a></h2>
<p><strong>High-replenishment consumables</strong> (beauty, pet, F&amp;B): The benchmark should be 5:1 or above. These categories have the economics to support high LTV — high gross margin, frequent repeat purchases, predictable consumption cycles. A sub-4:1 ratio in these categories usually indicates an acquisition efficiency problem or a retention problem. Both are fixable.</p>
<p><strong>Fashion and apparel</strong>: 3:1 is roughly median. Optimise for repeat purchase rate (which is the main LTV lever in this category) before assuming an acquisition problem. A fashion brand at 2.5:1 that improves repeat purchase rate from 28% to 38% will see a meaningful ratio improvement without touching acquisition costs.</p>
<p><strong>Electronics</strong>: 2:1 can be healthy. The category is structurally different — per-unit revenue is high but repeat frequency is low. A consumer electronics brand at 2.1:1 is at the median and should not feel pressure to match a benchmark designed for a consumables business.</p>
<p><strong>Home and garden</strong>: 2.5:1 is reasonable given purchase frequency. The LTV uplift opportunity is usually cross-category (furniture → accessories → tools) rather than repeat purchase of the same SKU.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="accessing-ltv-benchmarks-via-api">Accessing LTV<!-- -->:CAC<!-- --> benchmarks via API<a href="https://docs.valcr.site/blog/ltv-cac-ratio-benchmarks#accessing-ltv-benchmarks-via-api" class="hash-link" aria-label="Direct link to accessing-ltv-benchmarks-via-api" title="Direct link to accessing-ltv-benchmarks-via-api" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> requests</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Get the LTV:CAC distribution for a segment</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">r </span><span class="token operator">=</span><span class="token plain"> requests</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"https://api.valcr.site/data/v1/benchmarks"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    headers</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"Authorization"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Bearer vcr_live_your_key"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    params</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"category"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ecommerce"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"segment"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"beauty"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">metrics </span><span class="token operator">=</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"metrics"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">ltv_cac </span><span class="token operator">=</span><span class="token plain"> metrics</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"ltv_cac_ratio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Beauty LTV:CAC p50: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">ltv_cac</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'p50'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation format-spec">.1f</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">x, p75: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">ltv_cac</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'p75'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation format-spec">.1f</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">x"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Rank a specific merchant's LTV:CAC</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">r2 </span><span class="token operator">=</span><span class="token plain"> requests</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"https://api.valcr.site/data/v1/benchmarks/percentile"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    headers</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"Authorization"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Bearer vcr_live_your_key"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    params</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"metric"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">   </span><span class="token string" style="color:rgb(255, 121, 198)">"ltv_cac_ratio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">    </span><span class="token number">5.8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"category"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ecommerce"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"segment"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"beauty"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Merchant is at the </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">r2</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">json</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'percentile'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation format-spec">.0f</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">th percentile"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-number-to-watch-alongside-ltv">The number to watch alongside LTV<!-- -->:CAC<a href="https://docs.valcr.site/blog/ltv-cac-ratio-benchmarks#the-number-to-watch-alongside-ltv" class="hash-link" aria-label="Direct link to the-number-to-watch-alongside-ltv" title="Direct link to the-number-to-watch-alongside-ltv" translate="no">​</a></h2>
<p>LTV<!-- -->:CAC<!-- --> in isolation is incomplete. The payback period — how many months of gross margin it takes to recover the acquisition cost — is equally important for cash flow management.</p>
<p>A 6:1 LTV<!-- -->:CAC<!-- --> ratio with a 36-month payback period is a cash flow problem even if the unit economics eventually work. A 3:1 ratio with a 9-month payback is often more operationally sound.</p>
<p>Payback period = <code>CAC / (AOV × gross_margin × purchase_frequency_per_month)</code></p>
<p>The Valcr benchmark dataset includes payback period distributions within the customer economics metric set. At median for ecommerce broadly: 11 months. Top quartile: under 7 months. Bottom quartile: over 18 months.</p>
<hr>
<p><em>Data from the Valcr Q4 2024 benchmark pool. All calculations use VCFS-normalised LTV and CAC methodology.</em></p>
<p><a class="" href="https://docs.valcr.site/api/benchmarks">Access customer economics benchmarks →</a> · <a class="" href="https://docs.valcr.site/guides/vcfs-schema#customers-object">VCFS field definitions →</a></p>]]></content:encoded>
            <category>benchmarks</category>
            <category>data</category>
            <category>ltv</category>
            <category>cac</category>
            <category>customer-economics</category>
        </item>
        <item>
            <title><![CDATA[Why Valcr Is Infrastructure, Not Analytics]]></title>
            <link>https://docs.valcr.site/blog/infrastructure-not-analytics</link>
            <guid>https://docs.valcr.site/blog/infrastructure-not-analytics</guid>
            <pubDate>Tue, 29 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Why Valcr is financial data infrastructure for commerce, not an analytics product — the Stripe/Plaid analogy and the compounding dataset thesis.]]></description>
            <content:encoded><![CDATA[<p>The most common misreading of what Valcr does is to categorise it as an analytics product. An ecommerce dashboard. A benchmarking tool. A reporting layer.</p>
<p>These descriptions are not wrong exactly — Valcr does produce analytics, benchmarks, and reports. But they point to the wrong part of the product. And that distinction matters enormously, because analytics and infrastructure are different businesses with different economics, different buyers, and different reasons to exist.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-analytics-does">What analytics does<a href="https://docs.valcr.site/blog/infrastructure-not-analytics#what-analytics-does" class="hash-link" aria-label="Direct link to What analytics does" title="Direct link to What analytics does" translate="no">​</a></h2>
<p>An analytics product takes your data and shows it back to you in a more useful form. A well-designed analytics product surfaces patterns you would have missed, answers questions faster than a spreadsheet would, and helps you make better decisions.</p>
<p>Analytics is valuable. But it has a characteristic problem: it is downstream of the data. The data exists somewhere. The analytics product reads it, transforms it, and displays it. The intelligence produced is, ultimately, a function of the input data — and the input data is almost always the customer's own.</p>
<p>This creates a ceiling. An analytics product can only tell you things that are knowable from your own data. And most of the most important questions in business cannot be answered from your own data alone.</p>
<p>"Is my gross margin good?" Your analytics product knows your gross margin. It does not know what a comparable business's gross margin looks like. It cannot tell you whether 44% is exceptional or mediocre without something to compare it against.</p>
<p>That something is what Valcr is.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-infrastructure-does">What infrastructure does<a href="https://docs.valcr.site/blog/infrastructure-not-analytics#what-infrastructure-does" class="hash-link" aria-label="Direct link to What infrastructure does" title="Direct link to What infrastructure does" translate="no">​</a></h2>
<p>Infrastructure sits beneath other products and enables capabilities that those products could not economically build themselves.</p>
<p>Stripe is infrastructure. Every developer who integrates Stripe could, in principle, build their own payment processing system. Almost none of them do — because the build cost is enormous, the maintenance burden is ongoing, the regulatory complexity is significant, and Stripe's product is already better than anything a single engineering team would produce as a side project to their main product.</p>
<p>The result is that Stripe becomes embedded in thousands of products. The switching cost is real — moving payment infrastructure is a multi-month project. And Stripe's value compounds with scale because the fraud models, the bank relationships, and the reliability that come from processing trillions in volume cannot be replicated by a newer entrant.</p>
<p>Plaid is infrastructure. Plaid normalises bank data from thousands of financial institutions into a single API. Every application that builds on Plaid — budgeting apps, lending products, payroll tools — could theoretically negotiate direct data agreements with each bank. None of them do.</p>
<p>Valcr is in this category. The benchmark dataset that powers the API cannot be assembled by a SaaS accounting platform as a side project. Building a representative benchmark pool requires:</p>
<ul>
<li class="">Recruiting a sufficiently large, demographically representative merchant sample</li>
<li class="">Designing a normalisation methodology that produces comparable numbers across merchants using different accounting approaches</li>
<li class="">Maintaining the dataset as the sample grows and the merchant universe shifts</li>
<li class="">Computing distributions per segment with sufficient sample depth to produce credible percentile data</li>
<li class="">Updating it regularly enough to remain accurate</li>
</ul>
<p>This is not analytics. This is data infrastructure — the kind of foundational capability that enables other products to offer analytics features they could not otherwise provide.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-correct-one-liner">The correct one-liner<a href="https://docs.valcr.site/blog/infrastructure-not-analytics#the-correct-one-liner" class="hash-link" aria-label="Direct link to The correct one-liner" title="Direct link to The correct one-liner" translate="no">​</a></h2>
<blockquote>
<p>Valcr is financial benchmarking infrastructure for commerce — operator tools on the surface, proprietary financial dataset underneath.</p>
</blockquote>
<p>The "operator tools on the surface" part — the dashboard, the benchmarking UI, the Valcr Score display — are the consumer interface. They are how direct users experience the product. They matter and they will keep improving.</p>
<p>The "proprietary financial dataset underneath" is the infrastructure layer. It is what the API serves. It is what compounds in value as the merchant pool grows. It is what gives Valcr the same characteristic that good infrastructure always has: it becomes more valuable to every user as the total number of users grows.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-this-distinction-matters-for-buyers">Why this distinction matters for buyers<a href="https://docs.valcr.site/blog/infrastructure-not-analytics#why-this-distinction-matters-for-buyers" class="hash-link" aria-label="Direct link to Why this distinction matters for buyers" title="Direct link to Why this distinction matters for buyers" translate="no">​</a></h2>
<p><strong>For SaaS platforms and developers:</strong> You are not buying a dashboard to embed. You are licensing access to a dataset and the normalisation infrastructure that makes it useful. The value proposition is the same as Stripe's or Plaid's — you get a capability that would cost you orders of magnitude more to build yourself, delivered via an API you can integrate in a day.</p>
<p><strong>For lenders and underwriters:</strong> You are not buying a reporting tool. You are buying the ability to contextualise a merchant's financials against their actual peer group at the moment of underwriting. That context is not available anywhere else in a normalised, API-accessible form. It integrates into your existing pipeline; it does not replace it.</p>
<p><strong>For commerce operators:</strong> The dashboard and the benchmarks are genuinely useful — but the deeper value is that your VCFS profile, once submitted, produces intelligence that improves as the benchmark pool grows. You contributed data to a system that makes the benchmarks more precise, and you benefit from every other merchant who does the same.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-compounding-dataset">The compounding dataset<a href="https://docs.valcr.site/blog/infrastructure-not-analytics#the-compounding-dataset" class="hash-link" aria-label="Direct link to The compounding dataset" title="Direct link to The compounding dataset" translate="no">​</a></h2>
<p>This is the part that is hardest to communicate quickly but most important to understand about Valcr's long-term position.</p>
<p>Every merchant whose VCFS data enters the Valcr pipeline deepens the benchmark distributions — more observations, more precise percentiles, narrower confidence intervals, better sub-segment coverage. The benchmarks that the API serves in 2026 will be materially more credible than the benchmarks it serves today, because the dataset will be larger.</p>
<p>This compounding does not happen in analytics products. Adding a new user to a dashboarding tool makes the vendor's revenue larger. It does not make the product more valuable to existing users.</p>
<p>Adding a new merchant to the Valcr benchmark pool makes the platform more valuable to every lender, every developer, every operator who queries the API. That is the infrastructure model. And it is a fundamentally different business.</p>
<hr>
<p><a class="" href="https://docs.valcr.site/guides/vcfs-schema">Read more about the data model →</a> · <a class="" href="https://docs.valcr.site/quickstart">Start building with the API →</a></p>]]></content:encoded>
            <category>product</category>
            <category>strategy</category>
            <category>infrastructure</category>
            <category>positioning</category>
        </item>
    </channel>
</rss>