Calculated Pricing supports FUNCTIONS starting today. Quote rules can set a line item property with a formula too. Here's how to build both.
OK... I'm really excited about this — but at the same time, I know it's been a long time coming. Nonetheless, functions are finally here in Quotivity's Calculated Pricing.
Calculated Pricing has always done arithmetic. Add, subtract, multiply, divide, wrap things in parentheses, pull values off the line item, the quote, a rollup, the deal, or the company. That covers most of what a pricing team needs.
What it could never do was make a decision. The formula ran the same way every time, no matter what was on the quote.
Most teams solved that with a HubSpot line item calculated property. You'd leave Quotivity, build a calculation property in HubSpot that did the branching, come back, and point the calculated price at the result. It works, and plenty of good pricing setups run on it today. It also means the logic for one price lives in two systems, and the person debugging a wrong number has to open both to see the whole picture.
Two releases shipped today that make the round trip unnecessary. Formulas now support conditional logic. And the Update Line Item outcome in quote rules can set a property with a formula instead of a static value or a copy from another field.
If you know Excel, you already know most of this
They behave the way their Excel and Google Sheets counterparts do. Same syntax, same argument order.
| Function | Excel and Sheets | What's different in Quotivity |
|---|---|---|
IF(condition, value_if_true, value_if_false) |
Same function, same three arguments, same order | Nesting caps at 5 levels and 10 IFs per formula |
AND(condition1, condition2, ...) |
Same. True only when every condition is true | Takes up to 5 conditions, where Excel takes far more |
OR(condition1, condition2, ...) |
Same. True when any condition is true | Takes up to 5 conditions |
NOT(condition) |
Same. Flips true and false | No difference |
ISBLANK(value) |
Same idea, stricter in Excel | Unset values and whitespace-only text both count as blank. 0 and FALSE do not |
BLANKVALUE(value, fallback) |
Sheets and Excel make you write |
The short version, built in |
Comparison operators work the way you'd expect too: =, != or <>, >, <, >=, <=. Text comparisons ignore case, so "Renewal" and "renewal" match.
We'll be adding more functions as we go, but felt this was a good place to start. we'll be adding more functions as we go, but felt this was a good place to start.
Here is what building with them looks like.
Or skip the syntax and describe it
The formula editor drafts for you now. Type what the price is supposed to do in plain English, something like "twenty percent off at 250 seats, fifteen at 100, ten at 25," and Quotivity writes the formula, using your actual property names.
It knows the function set, including the ones that shipped today, so the draft comes back with the right nesting and the right argument order. You still read it before you save it. But the part people put off, getting the parentheses to line up on a four-level nested IF, is no longer the reason a pricing change waits until Friday.
Cadence Analytics sells a seat-based annual subscription. List price is $120 per seat per year, and the discount follows the seat count: 10% off at 25 seats, 15% off at 100, 20% off at 250.
Renewals work differently. A renewing customer keeps the tier they earned, and finance applies a 5% uplift on top of last year's price. That uplift is the whole reason renewal ARR grows without anyone selling anything.
Some accounts are exempt. Cadence signs multi-year price locks, and a locked account holds its rate. The lock is recorded on the company record, and which year of the contract a deal represents is recorded on the deal.
Step one, the new business formula
Open Calculated Pricing, create a price, and assign it to the subscription product. The tier logic goes in as nested IF statements, most expensive tier first.
IF(Quantity >= 250,
List Price * 0.80,
IF(Quantity >= 100,
List Price * 0.85,
IF(Quantity >= 25,
List Price * 0.90,
List Price
)
)
)
Read it top to bottom the way the engine does. If the quantity clears 250, take 20% off and stop. If not, check 100. If not, check 25. If none of them hit, the customer pays list.
Order matters, and it's the one thing worth double-checking. Write the 25-seat test first and every deal in the catalog gets 10% while the higher tiers never fire.
Turn on the rounding option while you're in there. New formulas round results to two decimals by default, which keeps $102.0000001 out of your quotes.
Step two, the renewal variation
Same tiers, plus the uplift. The renewal price starts from what the customer actually paid last year, so the formula reaches for a Prior Unit Price property on the line item and multiplies.
Prior Unit Price * 1.05
That's the simple version. It also bills every price-locked account 5% more than their contract allows, so it needs a condition.
IF(AND(Price Locked = FALSE, Contract Year > 1),
Prior Unit Price * 1.05,
Prior Unit Price
)
Price Locked is a company property. Contract Year is a deal property. Neither one lives on the line item, and the formula reads them anyway. Hold that thought, because it's the part that matters most.
There's still one way this breaks, and it's the common one. Prior Unit Price is empty for anybody who has never renewed. A blank number reads as zero, so a first-year customer landing on this formula prices at zero times 1.05, which is a quote for nothing.
BLANKVALUE, shipping today alongside the rest, handles that in one wrap.
IF(AND(Price Locked = FALSE, Contract Year > 1),
BLANKVALUE(Prior Unit Price, List Price) * 1.05,
BLANKVALUE(Prior Unit Price, List Price)
)
Use the prior price when there is one, fall back to list when there isn't. Worth remembering that 0 and FALSE are not blank, so a property genuinely set to zero stays zero.
The last case Cadence hits often is a renewing customer who's also expanding. They bought 80 seats last year and they're renewing at 300. Uplifting last year's price would charge them more per seat while they're buying four times as many, which is a fast way to lose a renewal conversation. So the formula gives them whichever price they've earned.
IF(Quantity >= 250,
List Price * 0.80,
IF(
AND(Price Locked = FALSE, Contract Year > 1),
BLANKVALUE(Prior Unit Price, List Price) * 1.05,
BLANKVALUE(Prior Unit Price, List Price)
)
)
Expansion past 250 seats gets the 20% tier. Everything else follows the uplift rule. Two branches of logic, one formula.
Why this isn't the same as a HubSpot calculated property
Look back at that formula and count what it reads: quantity and prior price off the line item, the price lock off the company, the contract year off the deal.
A HubSpot line item calculated property can't do that. It only sees other properties on the same line item. Anything living on the deal, the company, the quote, or in a rollup is invisible to it.
So the old build had a step before the step. Copy Price Locked down from the company onto the line item, copy Contract Year down from the deal onto the line item, usually with a workflow or a quote rule, and only then can the calculated property do its branching. Now the pricing logic for one product is spread across a workflow, a HubSpot calculation property, and a Quotivity calculated price. Change the uplift from 5% to 4% and you have to remember which of the three holds that number.
Calculated pricing starts from a wider view. Line item, quote, rollup, deal, company, all available to the same formula, which means the copy-down step disappears and the branching happens where the price is defined. One object to open, one place to change it, one thing to hand to whoever covers for you.
That's the real upgrade here. The functions are ordinary. Being able to point them at everything on the deal is not.
What the rep sees
Nothing above. That's deliberate.
The Quote Builder used to show reps the whole formula with input fields dropped in where the variables were, which meant every rep saw the pricing logic and had to work out which boxes were theirs. Now the formula and every read-only value are hidden. The rep sees the fields they're responsible for filling in, and the price.
Calculations also run on the backend now, not just in the browser. Quotes created by automation get priced correctly, and a quote built by a rule at two in the morning comes out the same as one a rep builds by hand.
Step three, formulas inside quote rules
The second release is smaller and easier to miss.
The Update Line Item outcome could already set a property to a static value, or copy the value of another field. What it couldn't do was math. If you wanted a derived number on a line item, you built a calculated property somewhere else and pointed the rule at it, which is the same round trip in a different place.
Now there's a Set with Formula option right in the outcome, running the same function set.
Cadence uses it for reporting. Finance wants to know how much uplift the renewal book actually captured, per line, without exporting anything. So the rule writes it:
(Unit Price - BLANKVALUE(Prior Unit Price, Unit Price)) * Quantity
Set the rule's line item selection criteria to renewal subscription lines, pick the Uplift Captured property, choose Set with Formula, and that's the configuration. Every renewal line carries its own uplift number, in HubSpot, on the line item, where reporting already looks.
Three things to know about it:
The same option is on the Update Bundle Member outcome, so bundle components can carry derived values too.
Formulas are typed to the property you're updating. Pick a number property and the formula has to produce a number. That catches the mistake at build time instead of on a customer's quote.
Enumeration properties don't get the option. If the property you're updating is a dropdown, Set with Formula won't appear, and a static value or a field copy is still the way to set it.
The limits, honestly
Formulas cap at 2,000 characters, five levels of nesting, and ten IF functions each. Those numbers are high enough that most pricing logic never gets near them, and low enough that nobody builds something the engine can't evaluate in time.
Empty values read as zero for numbers and as false for conditions, which is usually what you want and occasionally isn't. BLANKVALUE is there for the times it isn't, and it's worth reaching for any time a property that drives a branch might be missing on some records.
A formula with a syntax error won't save. A formula that fails at runtime falls back rather than pricing at zero, and division by zero raises an error instead of quietly returning something wrong.
Where to start
Open your HubSpot line item calculated properties and find the ones that exist only to feed a Quotivity price. Those are the round trips. Most of them collapse into the formula they were feeding, and the workflows copying deal and company values down onto line items can usually go with them.
Then look at the calculated prices that exist in pairs. New business and renewal. Direct and partner. Domestic and international. Any pair that differs by one condition is now one formula, and collapsing it is usually a fifteen-minute job.
Pricing logic that lives in one place is pricing logic somebody other than you can read.
