Learn GTM & Sales Automation jq for GTM
Data cleanupjq for GTM: edit big JSON exports without breaking them
Half the tools in a GTM stack export JSON, and nobody teaches you what to do with it. One free command-line tool does most of the work, and this guide walks through it from install to a safe merge.
I keep my project board in a kanban app. Last week I had 26 new cards to add, so I did what anyone would do: opened the export file and tried to paste them in. My computer froze. Twice.
The file was only about 100 KB, which is tiny. The problem was its shape. Exports like this are usually one enormous line with no breaks, and most text editors and browser boxes hate that. Even when it doesn't freeze, a single missing comma anywhere in the paste makes the whole file unimportable, and the error message won't tell you where.
The fix was to stop editing the file by hand at all. A small tool called jq read both files, added the new records to the right list, skipped anything that was already there, and wrote a fresh copy. It took under a second. If you work with Clay, n8n or any CRM export, the same trick applies to you.
Where you'll run into it
JSON is already in your stack
JSON is a plain-text way of storing lists of things with labeled fields. Spreadsheets flatten it badly, which is why these files pile up unopened.
Clay
Table and workbook exports, and the JSON your HTTP columns return.
n8n
Whole workflow files, which are just JSON, plus execution data.
CRM and enrichment APIs
Apollo, HubSpot and similar tools answer in JSON, often nested three levels deep.
Sequencer webhooks
Reply, bounce and open events from tools like Smartlead or Instantly.
App backups
Kanban boards, note apps and Chrome extensions export everything as one JSON file.
Install jq in a minute
Open a terminal (Terminal on Mac, PowerShell on Windows) and paste the line for your system.
brew install jq sudo apt install jq sudo dnf install jq winget install jqlang.jq
Type jq --version
to check it worked. Then move to the folder that holds your export, or
give jq the full path to it.
Cheat sheet
Eight jq commands that cover most GTM work
The examples assume a file called export.json with a list named contacts. Swap in your own file and list names. Run the top ones first on any file you don't know yet.
| I want to | Command | What I get |
|---|---|---|
| Check the file is valid | jq empty export.json | Prints nothing if the file is fine. Prints the line and column of the problem if it is not. |
| Make it readable | jq . export.json > readable.json | A copy with one field per line, so a text editor stops choking on it. |
| See what is inside | jq keys export.json | The top-level sections, like contacts, companies or notes. |
| Count records | jq ".contacts | length" export.json | A single number. Run it before and after any change. |
| Peek at one record | jq ".contacts[0]" export.json | The first contact with every field, so you can see the shape. |
| Filter rows | jq ".contacts[] | select(.status == \"bounced\")" export.json | Only the contacts whose status is bounced. |
| Pull columns into a CSV | jq -r ".contacts[] | [.email, .company] | @csv" export.json | Two columns you can open straight in Sheets. |
| Find duplicate emails | jq "[.contacts[].email] | group_by(.) | map(select(length > 1) | .[0])" export.json | The list of emails that show up more than once. |
Two notes. On Windows PowerShell, swap the inner double quotes for single quotes if a command complains. And the dot in the second command is not a typo, it means "the whole file".
Adding records without corrupting the export
Reading a file is easy. The part that scares people is changing it. This is the routine I follow every time, and it's boring on purpose.
- 1
Leave the original alone
Never edit the export you got from the tool. Copy it or, better, let the command write a brand new file next to it. If something goes wrong you still have the file that worked.
- 2
Keep new records in their own file
Put the batch you want to add into a separate file with the same structure as the export. That file is easy to review on its own, and you can rerun the merge if you fix a typo in it.
- 3
Match on the ID, not the name
Names get edited and duplicated. Every decent export gives each record an ID. Use it to decide whether a record is already there. That one habit makes the merge safe to run twice.
- 4
Keep related records together
Exports often store a card and its note, or a contact and its activity, in two separate lists that point at each other through an ID. Add both sides in the same run, or you end up with orphans.
- 5
Check the counts before you trust it
Count the records before and after. If you added 26 and the total went up by 26, good. If it went up by 0, your rows were already there. If it went up by 52, you doubled them.
When I ran my own merge a second time, the counts didn't move. That's the result you want. It means the command can't double-add records if you forget you already ran it, which is exactly the mistake that hand-pasting invites.
You don't have to write the jq yourself
jq's filter language looks like line noise until you've used it a few times. Most people I know describe the job to an AI assistant and let it write the command, then use the cheat sheet above to check the result. Give it four things:
- One real record from each file, pasted in, with any private data blanked out.
- The names of the lists you want to combine.
- The field that identifies a record, so duplicates get skipped.
- The rule for the output: write a new file, never touch the original, and print the counts before and after.
Then run it on a copy first. If the counts match what you expected, use it on the real file. If they don't, paste the numbers back and ask why.
Where this goes wrong
Records that link to each other are the classic trap. If you add a contact but not its activity list, the app may import fine and show blank cards. Check that every record you add points at a list that exists.
Timestamps are the second one. Many exports store dates as long numbers counting milliseconds, not readable dates. If you type your own, copy the format of the records already in the file.
And jq only knows about the file. It can't tell you whether the app on the other end will accept it. Import the merged file somewhere harmless first, or keep the previous export around so you can roll back.
Common questions
FAQ: jq and JSON exports
Keep going
More GTM and sales automation breakdowns, built the same way.