Define custom metrics
A custom metric is a column you create yourself by writing a tiny arithmetic formula. ROAS, CPM, cost-per-conversion — anything that's a function of impressions, clicks, conversions, and spend.
What custom metrics are
Crowflow ships with four base metrics — impressions, clicks, conversions, spend — and four derived ones (CTR, CR, CPC, CPA) on every row. Custom metrics let you add your own derived columns by writing a formula.
Custom metrics are available on the Starter and Pro plans. The built-in derived columns (CTR, CR, CPC, CPA) are on every plan, including Free.
Manage them at /app/settings/metrics. Each metric has a name (the column header), a formula, an output format, and an optional description.
Variables you can use
Exactly four:
impressionsclicksconversionsspend
results still works as a variable name and refers to the same value as conversions. Older formulas you wrote when the column was called Results keep working untouched — use either name in new formulas.These are the base columns synced from every ad platform. CTR, CR, CPC, and CPA are notexposed as variables — they’re already derivable from the four above, and letting you reference them would create self-referential nonsense like ctr / ctrthat doesn’t do what it looks like.
Operators & syntax
Five operators plus parentheses for grouping:
+addition-subtraction (and unary negation)*multiplication/division( )grouping
You can also use numeric literals — integers and decimals:
(spend / impressions) * 1000
No function calls (min(), max(),if()), no string operations, no comparisons. If you need conditional logic, build two metrics and pick which one you’re looking at in your analysis.
Output formats
Pick how the computed value renders in the dashboard:
- Number — a plain decimal. e.g.
3.45. Sensible for ratios like ROAS, view-through rates, etc. - Percentage — appends a
%suffix. e.g.2.34%. Use for any rate-style metric - Currency— prefixes the row’s currency symbol. e.g.
£12.34. Use for spend-derived metrics like CPM
Examples to copy
The Settings → Custom metrics page has four quick-start examples you can apply with one click. Here they are with context:
- Cost per conversion —
spend / conversions· format: Currency. Spend divided by the number of conversions — your cost per acquisition. (Identical to the built-in CPA column; defining it as a custom metric lets you give it a different name or format.) - CPM —
(spend / impressions) * 1000· format: Currency. Cost per thousand impressions - Estimated ROAS —
(conversions * 25) / spend· format: Number. Return on ad spend assuming each conversion is worth £25 to your business — edit the 25 to your actual average order value - Cost per 100 conversions —
(spend / conversions) * 100· format: Currency. Useful when conversions are cheap and the per-unit number is hard to read
revenue / spend, but Crowflow doesn’t sync revenue — only the count of conversions reported by each ad platform. If your conversions have a consistent value (£25/lead, £80/purchase), multiply conversions by that value to get estimated revenue, then divide by spend. If your values vary a lot, ROAS computed this way will be wrong; consider tracking revenue in your Sheet manually.Note: Conversion rate((conversions / clicks) × 100) is now a built-in column called CR— you don’t need to define it as a custom metric.
Other ideas worth defining:
- Clicks per impression (raw) —
clicks / impressions· format: Number. Same as CTR but expressed as a 0–1 ratio rather than a percentage - CPC goal delta —
spend - (clicks * 0.50)· format: Currency. How far over (positive) or under (negative) you ran vs a £0.50 CPC target - Estimated profit at target margin —
(conversions * 25) - spend· format: Currency. Same assumption as Estimated ROAS — gross profit if each conversion is worth £25
Using them in the dashboard
Every custom metric appears as a column in the dashboard table, alongside the built-in columns. It’s:
- Sortable— click the column header
- Toggleable— show or hide via the Columns dropdown
- Re-computed for every Group by— daily grain, weekly, monthly, yearly. The math is correct at each level (see Rollup below)
The Columns dropdown groups custom metrics under their own “Custom metrics” sub-heading. There’s also a “+ Custom metric” shortcut in the dropdown so you can jump straight to Settings to add a new one.
Using them in Sheet exports
Custom metrics are first-class in the customise exportUI too. The Metrics section lists every built-in metric, then a “Custom” sub-section with your defined metrics — tick the ones you want in the Sheet.
If you delete a custom metric that’s still referenced by a destination’s export, the column header in the Sheet reads “(deleted metric)” and the cells render empty. Open Customise export and untick the stale reference to clean up.
How rollups work
Custom metrics roll up the same way the built-in rate metrics do: derived from the summed base totals, not averaged from per-row rates.
For Cost per conversion at the dashboard’s totals strip:
Cost_per_conversion_total = sum(spend) / sum(conversions) NOT average of per-row cost-per-conversion values
This is the only mathematically correct way to roll up a ratio. If you switch Group by from Day to Month, your custom column shows the metric for each month (sum of conversions in the month divided by sum of spend, etc.), not the average of the 30 daily values.
Common formula errors
The Create / Edit form shows a live “✓ Valid” or “Invalid: <reason>” under the formula field as you type. Common reasons a formula is rejected:
- “unknown variable”— you typed something other than the four allowed names. Check spelling; it’s case-insensitive but otherwise strict
- “expected closing ‘)’” — unbalanced parentheses
- “unexpected end of formula” — you stopped mid-expression, e.g.
spend / - “extra tokens after end of expression” — usually a stray
)or punctuation after a valid sub-expression - “formula is empty” — you cleared the field. Save is blocked
- “a metric named X already exists” — names are unique per workspace; pick a different one
What the parser does & doesn't allow
The formula engine is a small recursive-descent parser written specifically for Crowflow. It has no JavaScript interop, no eval(), no function calls. The only things it can do are:
- Read the four base variables
- Add, subtract, multiply, divide
- Group with parentheses
- Use numeric literals
That’s it. A malformed or malicious input throws a FormulaError at parse time — it never executes. We chose this tight grammar deliberately: the cost of supporting custom formulas is acceptable because the surface area is small. If you have a use case that needs more (date functions, conditional logic), email hello@crowflow.ioand we’ll talk through whether a different feature is the right shape.