Skip to content

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.

Apollo Studio

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.

graphql
query PortfolioFunnelSteps($teamId: Int!, $portfolioId: Int!) {
  portfolioV2(teamId: $teamId, portfolioId: $portfolioId) {
    funnelSteps {
      funnelStepId
      title
      type
    }
  }
}

Example response:

json
{
  "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

graphql
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:

json
{
  "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:

IndexFunnel stepBaseline metricPredicted metricChange
0Cost18,20018,2000%
1Impressions940,0001,020,000+8.5%
2Clicks62,00070,000+12.9%
3Orders1,4501,720+18.6%
4Revenue87,000105,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

FieldDescription
totalBudgetTotal budget amount for the optimization period
budget.spentAmount already spent so far in the period
budget.proposedTotal budget the optimization is working with
metric.baselinePredicted value with the current allocation
metric.predictedPredicted value after applying the proposal
metric.changePercent((predicted − baseline) / baseline) × 100
costPer.baselineCost per unit of this metric with current allocation
costPer.predictedCost 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.