Skip to content

Line graph parser broken: API returns series objects, parser expects [date, value] pairs #73

@AlexGodard

Description

@AlexGodard

Summary

The InsightParser cannot parse line graph insights from the current PostHog API. The parser expects time-series data as [[date, value], ...] pairs, but the API returns a single series object containing separate data and days arrays. This causes all line graph insights to silently fail detection and display as zero/error.

Root Cause

In InsightParser::private_hasLineGraphStructure() (InsightParser.cpp L187-219), the very first check fails:

JsonArrayConst timeseriesData = firstResult[JSON_KEY_RESULT];
if (timeseriesData.isNull() || timeseriesData.size() <= 1) return false;
// "Needs at least 2 points for a line graph"

results[0].result has 1 element (the series object), so size() <= 1 is true and detection bails immediately.

What the parser expects

{
  "results": [{
    "result": [
      ["2026-01-13", 8],
      ["2026-01-14", 2],
      ["2026-01-15", 13]
    ]
  }]
}

The data extraction methods (getSeriesYValues, getSeriesXLabel, getSeriesRange) all read result[i][0] as a date string and result[i][1] as a numeric value.

What the PostHog API actually returns

{
  "results": [{
    "result": [{
      "data": [8, 2, 13, 19, 5, 5, 7, ...],
      "days": ["2026-01-13", "2026-01-14", "2026-01-15", ...],
      "labels": ["13-Jan-2026", "14-Jan-2026", "15-Jan-2026", ...],
      "count": 155,
      "label": "$pageview"
    }]
  }]
}

This format is returned regardless of whether the insight is created with the legacy filters parameter or the new query parameter.

Additionally: query.display is not populated for new-format insights

For insights created with the new InsightVizNode / TrendsQuery format:

  • filters is {} (empty)
  • query.display does not exist (display is at query.source.trendsFilter.display)

This breaks the fallback display-type check on L204-207. Insights created with the legacy filters param have query: null, so this check also fails.

Suggested Fix

Update private_hasLineGraphStructure() and the data extraction methods to handle the current format:

bool InsightParser::private_hasLineGraphStructure() const {
    if (!valid) return false;

    JsonArrayConst results = m_insightDataRoot[JSON_KEY_RESULTS];
    if (results.isNull() || results.size() == 0) return false;

    JsonObjectConst firstResult = results[0];
    if (firstResult.isNull()) return false;

    JsonArrayConst resultArray = firstResult[JSON_KEY_RESULT];
    if (resultArray.isNull() || resultArray.size() == 0) return false;

    JsonVariantConst firstElement = resultArray[0];

    // New format: result[0] is an object with "data" and "days" arrays
    if (firstElement.is<JsonObjectConst>()) {
        JsonObjectConst series = firstElement.as<JsonObjectConst>();
        JsonArrayConst data = series["data"];
        JsonArrayConst days = series["days"];
        return !data.isNull() && !days.isNull() && data.size() >= 2;
    }

    // Legacy format: result is [[date, value], [date, value], ...]
    if (resultArray.size() <= 1) return false;
    JsonArrayConst firstPoint = resultArray[0];
    if (firstPoint.isNull() || firstPoint.size() != 2) return false;
    const char* dateStr = firstPoint[0];
    if (!dateStr || strlen(dateStr) < 10) return false;
    return firstPoint[1].is<double>();
}

Similarly, getSeriesPointCount, getSeriesYValues, getSeriesXLabel, and getSeriesRange would need to read from result[0].data and result[0].days instead of result[i][0] / result[i][1].

Impact

  • BoldNumber insights work (the aggregated_value field is present in the current API format)
  • Line graphs are completely broken for all users
  • Funnel insights may also be affected depending on their API format

Environment

  • Firmware: 0.1.5
  • PostHog region: US
  • Parser source: current main branch has the same issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions