Learn

Practical coding & SQL for GTM

Enough code and SQL to get past what no-code tools can do, and to trust your own numbers.

Roadmap: GTM foundations & technical baseline, CRM, RevOps & automation

Why it matters

Many GTM engineers start in no-code tools and hit a wall: a provider with no native integration, a 50,000-row cleanup, a report the CRM can't build, a webhook that needs a signature check. A little JavaScript or Python and solid SQL let you solve those directly instead of stacking more tools. It's also what separates "GTM engineer" from "Clay operator" in job posts and interviews.

What it's made of

  • Calling REST APIs: auth headers, pagination, rate limits, error codes
  • Reading and transforming JSON (formulas, JS snippets, Python)
  • SQL joins, GROUP BY and window functions on CRM data
  • Normalising domains, names, titles and phone numbers
  • Deduplication logic and fuzzy matching
  • Small scripts and serverless functions for glue work
  • Using AI coding tools well, and checking their output

The API checklist

Almost every enrichment, CRM and sending tool exposes a REST API. Before you wire one up, answer:

  • Auth: API key in a header, OAuth, or both? Where will the secret live (never in a shared table cell)?
  • Pagination: cursor or page number? What tells you there are no more pages?
  • Rate limits: requests per second or per day, and what does the 429 response look like?
  • Errors: which codes are worth retrying (429, 5xx) and which mean stop (400, 401, 404)?
  • Cost: is each call billed, and does a "no result" still cost a credit?

Normalise before you match

Most GTM data bugs are matching bugs. Normalise domains by lowercasing, stripping protocol, "www." and paths (https://www.Acme.io/about → acme.io). Strip legal suffixes from company names only for display, never as a join key. Standardise titles into buckets ("VP Sales", "Head of Sales", "SVP, Revenue" → sales leadership) with a lookup table you can edit, not a giant nested IF.

SQL patterns you'll use every week

Once CRM and sequence data land in a warehouse, these four patterns answer most questions:

  • Latest record per entity: ROW_NUMBER() OVER (PARTITION BY domain ORDER BY updated_at DESC) = 1.
  • Funnel counts: COUNT(DISTINCT CASE WHEN stage >= 'meeting' THEN contact_id END) by campaign.
  • First touch: MIN(activity_at) per contact, joined back to see which campaign started the relationship.
  • Duplicate finder: GROUP BY normalised_domain HAVING COUNT(*) > 1.

Use AI to write code, not to own it

AI coding assistants are excellent for GTM glue: a webhook handler, a parser, a script that backfills a field. Treat their output like a junior's pull request. Run it on a handful of real rows including an empty value, a unicode name and a malformed domain. Check that it handles the second page and the rate-limit response. If you can't explain each line, you can't debug it when it breaks at 2 AM during a 20,000-row run.

Mid-level looks like

Writes formulas and short scripts that transform data, calls an API with a key, and writes basic SQL with joins and filters.

Senior looks like

Writes paginated, rate-limited, retry-safe API clients, models GTM data in a warehouse, and uses window functions to answer funnel questions the CRM can't.

Common pitfalls

  • Matching companies on name instead of a normalised domain, so "Acme Inc" and "ACME, Inc." become two accounts.
  • Pulling only the first page of an API response and not noticing the other 90%.
  • Pasting AI-generated code into a production workflow without running it on ten edge-case rows first.
  • Counting rows after a join without checking whether the join multiplied them.

Practice drills

  1. Drill 1

    Write a script that pulls every contact from a paginated API (100 per page), backs off on 429 responses, and writes a CSV. Test it against a mock that rate-limits every fifth call.

    A strong answer: A loop that terminates correctly, exponential backoff with a cap, no lost or duplicated rows, and the key read from an environment variable.

  2. Drill 2

    Given accounts, contacts and opportunities tables, write SQL for: meetings booked per campaign last quarter, and pipeline created per campaign with each opportunity counted once.

    A strong answer: Correct joins without double counting, a clear attribution rule stated up front, and DISTINCT or window functions used deliberately.

  3. Drill 3

    Take 500 messy company records and dedupe them. Report how many merges you'd make and list the ten you're least sure about.

    A strong answer: Domain normalisation, a match-confidence rule, a manual-review bucket instead of forced merges, and a reversible output.

Best resources for this skill

Repos, courses, articles and podcasts, ranked by how much they teach.

Read next

Next skillData sourcing & enrichment waterfalls