How to convert ga4 / mixpanel json export to csv
- Step 1Export from your analytics platform — GA4: runReport / Data API JSON, or a saved report export. Mixpanel: raw event export (NDJSON). Amplitude: export API (NDJSON). Drop the file onto the converter above; free files cap at 2 MB.
- Step 2Choose the input format — For Mixpanel/Amplitude raw events, use NDJSON / JSONL (or Auto detect). For a GA4 report JSON document, use Auto detect / JSON array after extracting the rows.
- Step 3For GA4, extract and ideally zip the rows first — GA4 nests data under
rowswith positionaldimensionValues/metricValues. Extract$.rowswith json-path-extractor; be aware the values flatten to indexed cells, so map them to names from the response headers or pre-shape the JSON. - Step 4Keep flattening on for Mixpanel/Amplitude — Flatten nested objects (default) turns
properties.utm_source,event_properties.plan, etc. into individual columns — ready for pivot tables. - Step 5Convert and check the event count — Click Convert to CSV. Records in should equal your event/row count. Sort by event name in your spreadsheet to profile event distribution.
- Step 6Download for analysis — Excel-Ready CSV (BOM + CRLF) for spreadsheets and BI; plain Download CSV (LF) for pandas / R / DuckDB.
Per-platform export shape and handling
Each analytics platform exports differently — match the approach to the source.
| Platform | Export shape | Handling |
|---|---|---|
| GA4 Data API | { rows: [ { dimensionValues:[...], metricValues:[...] } ] } | Extract $.rows; positional arrays flatten to indexed cells |
| Mixpanel raw export | NDJSON — one event per line, attrs under properties | NDJSON format; flatten properties |
| Amplitude export | NDJSON — events with event_properties / user_properties | NDJSON format; flatten both property objects |
| Saved report JSON | Varies; often { data: [...] } | Extract the array, then flatten |
How event fields flatten
Mixpanel / Amplitude event flattening example.
| Event field | CSV column | Note |
|---|---|---|
event | event | Event name — sort/group on this |
properties.utm_source | properties.utm_source | Flattened from the properties object |
properties.time | properties.time | Usually a Unix epoch — kept verbatim |
properties.tags (array) | properties.tags | One cell, per Array values setting |
Cookbook
Real analytics export shapes and the CSV the converter produces. User identifiers anonymised.
Mixpanel raw events to CSV
ExampleNDJSON events flatten so each property becomes a column, ready for a pivot table.
Input (mixpanel.ndjson):
{"event":"Signup","properties":{"utm_source":"google","plan":"free"}}
{"event":"Purchase","properties":{"utm_source":"email","plan":"pro"}}
Output CSV:
event,properties.utm_source,properties.plan
Signup,google,free
Purchase,email,proAmplitude events with two property objects
ExampleBoth event_properties and user_properties flatten into their own dot-notation columns.
Input:
{"event_type":"play","event_properties":{"track":"A"},"user_properties":{"tier":"pro"}}
Output CSV:
event_type,event_properties.track,user_properties.tier
play,A,proDiffering properties aligned
ExampleDifferent events carry different properties; the union header keeps every column with empties where unused.
Input:
{"event":"Signup","properties":{"plan":"free"}}
{"event":"Refund","properties":{"reason":"dup"}}
Output CSV:
event,properties.plan,properties.reason
Signup,free,
Refund,,dupGA4 positional arrays flatten to indexed cells
ExampleGA4's dimensionValues / metricValues are positional, so they flatten by index — map positions to names from the response headers.
Extracted $.rows:
[ { "dimensionValues":[{"value":"google"}], "metricValues":[{"value":"42"}] } ]
Output CSV (indexed):
dimensionValues.0.value,metricValues.0.value
google,42
Map: dimensionValues.0 = sessionSource, metricValues.0 = sessions.Multi-value property joined
ExampleAn array property reads better comma-joined in a spreadsheet column.
Input:
{"event":"View","properties":{"tags":["home","promo"]}}
Array values = Comma joined:
event,properties.tags
View,"home, promo"Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
GA4 columns are indexed, not named
By designGA4 dimensionValues / metricValues are positional arrays, so they flatten to dimensionValues.0.value style indexed columns. Map indexes to names using the response's dimensionHeaders / metricHeaders, or zip them into named keys before converting.
Timestamps stay as Unix epochs
By designEvent time fields are usually epoch integers (often milliseconds). The converter keeps them verbatim — convert to readable dates in your spreadsheet for analysis.
Different events have different properties
SupportedThe union-of-keys header gives every property a column across all event types, with empties where an event doesn't set it — ideal for a combined event table.
GA4 report wrapped with metadata
By designA GA4 response mixes rows with dimensionHeaders, metricHeaders, rowCount, etc. Extract $.rows first with json-path-extractor; otherwise the whole report collapses to one wide row.
One bad line in a raw NDJSON export
Invalid JSONA corrupt event line aborts with Invalid JSON on line N. Remove or fix that line — raw exports occasionally truncate the final line.
Nested array of sub-events
Not expandedAn array of objects inside an event stays in one cell. Extract that path and convert separately if you need one row per sub-event.
Export over the free 2 MB limit
BlockedFree conversions cap at 2 MB / 500 rows. Raw event exports are large — use Pro (100 MB / 100,000 rows) or export a smaller date range.
Empty result set
ExpectedA report or export with no events yields zero rows and an empty CSV, no error. Confirm your query window returned data.
Frequently asked questions
Why are my GA4 columns named with numbers like dimensionValues.0?
GA4 returns dimensions and metrics as positional arrays, not named pairs. The flattener indexes them (dimensionValues.0.value). Map each index to its name using the response's dimensionHeaders / metricHeaders, or pre-zip the JSON into named keys.
Does it read Mixpanel and Amplitude raw exports?
Yes. Those are NDJSON — one event per line. Use the NDJSON / JSONL input format (or Auto detect), and each event becomes a row.
How do I get event properties into columns?
Keep Flatten nested objects on (default). properties.utm_source, event_properties.plan, and so on each become dot-notation columns.
Why are my timestamps just big numbers?
Analytics platforms export Unix epoch times (often milliseconds). The converter keeps them verbatim. Convert to dates in your spreadsheet — for ms, divide by 1000 first.
Different events have different properties — will the CSV align?
Yes. The union-of-keys header includes every property across all events, leaving empty cells where an event doesn't set one.
Do I need to extract anything from a GA4 report?
Yes — extract $.rows first with json-path-extractor, because GA4 mixes rows with header and metadata fields. Otherwise the report collapses to a single wide row.
Does the tool compute any metrics or rates?
No. It only flattens and serialises. Values pass through exactly as exported — do any aggregation or rate math in your spreadsheet or notebook.
Is my event data uploaded?
No. Conversion runs in your browser. User-level event data, which can be identifying, never reaches a server.
How large an export can I convert?
Free: 2 MB / 500 rows. Pro: 100 MB / 100,000 rows. Raw event exports are big — narrow the date range or upgrade.
What about arrays inside an event?
They go into one cell (JSON, pipe, or comma). Arrays of objects are not expanded — extract that path separately for a row per element.
Can I load the CSV straight into pandas or DuckDB?
Yes. Use the plain Download CSV (LF, UTF-8) for those tools; reserve Excel-Ready CSV (BOM + CRLF) for spreadsheets that prefer it.
I need to flatten arbitrary nested analytics JSON, not just events. Any tool?
The standalone json-flattener flattens any JSON to dot-notation keys, and json-transposer helps when rows and columns are swapped from what you need.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.