Tutorial: Reading an optimization proposal
Nexoya's AI engine generates periodic budget reallocation proposals for each portfolio — called optimizations. This tutorial shows how to fetch the active optimization and interpret the results correctly.
An optimization compares two scenarios for each funnel step:
- Baseline — predicted outcome if you keep the current budget allocation
- Predicted — predicted outcome if you apply the proposed reallocation
The goal is typically to get more conversions or revenue for the same total spend, or the same results for less spend.
Step 1: Fetch the portfolio's funnel steps
The optimization response returns a funnelSteps array whose entries correspond index-for-index to the portfolio's own funnel step list. There are no funnel step IDs in the optimization response itself — you need to fetch the portfolio's funnel steps first so you can decode which optimization entry belongs to which metric.
query PortfolioFunnelSteps($teamId: Int!, $portfolioId: Int!) {
portfolioV2(teamId: $teamId, portfolioId: $portfolioId) {
funnelSteps {
funnelStepId
title
type
}
}
}Example response:
{
"data": {
"portfolioV2": {
"funnelSteps": [
{ "funnelStepId": 329, "type": "COST", "title": "Cost" },
{ "funnelStepId": 330, "type": "AWARENESS", "title": "Impressions" },
{ "funnelStepId": 331, "type": "CONSIDERATION", "title": "Clicks" },
{ "funnelStepId": 334, "type": "CONVERSION", "title": "Orders" },
{ "funnelStepId": 335, "type": "CONVERSION_VALUE", "title": "Revenue" }
]
}
}
}Keep this array. You will use the index positions (0, 1, 2, …) to label the optimization data in Step 3.
Step 2: Fetch the active optimization
query PortfolioOptimization($teamId: Int!, $portfolioId: Int!) {
portfolioV2(teamId: $teamId, portfolioId: $portfolioId) {
activeOptimization {
optimizationId
start
end
totalBudget
performance {
total {
budget {
spent
proposed
changePercent
}
funnelSteps {
metric {
baseline
predicted
changePercent
}
costPer {
baseline
predicted
changePercent
}
}
}
}
}
}
}Example response:
{
"data": {
"portfolioV2": {
"activeOptimization": {
"optimizationId": "opt_abc123",
"start": "2025-05-01",
"end": "2025-05-31",
"totalBudget": 50000,
"performance": {
"total": {
"budget": {
"spent": 18200,
"proposed": 50000,
"changePercent": 174.7
},
"funnelSteps": [
{
"metric": { "baseline": 18200, "predicted": 18200, "changePercent": 0 },
"costPer": { "baseline": null, "predicted": null, "changePercent": null }
},
{
"metric": { "baseline": 940000, "predicted": 1020000, "changePercent": 8.5 },
"costPer": { "baseline": 0.019, "predicted": 0.018, "changePercent": -5.3 }
},
{
"metric": { "baseline": 62000, "predicted": 70000, "changePercent": 12.9 },
"costPer": { "baseline": 0.29, "predicted": 0.26, "changePercent": -10.3 }
},
{
"metric": { "baseline": 1450, "predicted": 1720, "changePercent": 18.6 },
"costPer": { "baseline": 12.55, "predicted": 10.58, "changePercent": -15.7 }
},
{
"metric": { "baseline": 87000, "predicted": 105000, "changePercent": 20.7 },
"costPer": { "baseline": 0.21, "predicted": 0.17, "changePercent": -19.0 }
}
]
}
}
}
}
}
}Step 3: Map optimization entries to funnel steps
The funnelSteps array in the optimization response has the same length and same order as the portfolio's funnel steps. Join them by index:
| Index | Funnel step | Baseline metric | Predicted metric | Change |
|---|---|---|---|---|
| 0 | Cost | 18,200 | 18,200 | 0% |
| 1 | Impressions | 940,000 | 1,020,000 | +8.5% |
| 2 | Clicks | 62,000 | 70,000 | +12.9% |
| 3 | Orders | 1,450 | 1,720 | +18.6% |
| 4 | Revenue | 87,000 | 105,000 | +20.7% |
Reading this: if the team applies the proposed budget reallocation, Nexoya predicts +18.6% more orders and +20.7% more revenue for the same total spend of 50,000.
The costPer values let you track efficiency: cost-per-order drops from 12.55 to 10.58 (−15.7%), meaning each conversion becomes cheaper.
Key fields reference
| Field | Description |
|---|---|
totalBudget | Total budget amount for the optimization period |
budget.spent | Amount already spent so far in the period |
budget.proposed | Total budget the optimization is working with |
metric.baseline | Predicted value with the current allocation |
metric.predicted | Predicted value after applying the proposal |
metric.changePercent | ((predicted − baseline) / baseline) × 100 |
costPer.baseline | Cost per unit of this metric with current allocation |
costPer.predicted | Cost per unit after reallocation |
No active optimization
If activeOptimization returns null, either no optimization period is active yet or optimization is not enabled for this portfolio. Contact your Nexoya account manager to enable it.
Learn more
See how portfolio optimization works and understanding optimization uplift in the Nexoya help center.
