50 campaigns in the UI? Now they're TypeScript.

Import First. Rewrite Never. Pull your entire account into typed, editable campaign files — then diff, version, and apply like code.

Terminal
$ ads import

  Connecting to Google Ads (customer: 1112223333)...

  ✓  campaign/brand-search                  imported
  ✓  campaign/brand-search/core-keywords    imported
  ✓  campaign/competitor-targeting          imported
  ✓  campaign/retargeting                   imported
  ... 46 more resources

  50 campaigns · 127 ad groups · 384 keywords
  Written to campaigns/  — ready to modify.

You have 50 campaigns built up over years — budgets tuned, keywords researched, audiences refined.

Infrastructure-as-code sounds great. But you're not going to rewrite 50 campaigns from scratch.

Import pulls your live account directly into TypeScript. No rewriting, no data entry, no starting over.

Once it's in code, you own it: diff it, edit it, version it, apply changes with a plan.

How it works

Import from Google Ads

Run `ads import` and your entire Google Ads account is pulled into TypeScript files. Campaigns, ad groups, keywords, ads, extensions — everything normalized into clean, idiomatic code.

Terminal
$ ads import

  ✓  campaign/brand-search                  imported
  ✓  campaign/brand-search/core-keywords    imported
  ✓  campaign/competitor-targeting          imported
  ✓  campaign/retargeting                   imported

  50 campaigns · 127 ad groups · 384 keywords
  Written to campaigns/

Import from Meta

Same command, different provider. `ads import --provider meta` pulls your Meta campaigns into the same TypeScript format. One codebase, multiple platforms.

Terminal
$ ads import --provider meta

  ✓  campaign/acme-awareness             imported
  ✓  campaign/acme-awareness/video-feed  imported
  ✓  campaign/acme-retarget              imported

  12 campaigns · 34 ad sets · 87 ads
  Written to campaigns/

Clean, editable TypeScript output

Imported campaigns become real TypeScript — not a JSON dump. Readable names, typed helpers, ready to modify. Change a budget, add a keyword, ship with `ads apply`.

TypeScript
// campaigns/brand-search.ts  (generated by ads import)
import { google, daily, exact, phrase, headlines, descriptions, rsa, url } from '@upspawn/ads'

export default google.search('Acme — Brand Search', {
  budget: daily(40),
  bidding: 'maximize-clicks',
})
  .group('Core Keywords', {
    keywords: [...exact('acme'), ...phrase('ai workflow automation')],
    ad: rsa(
      headlines('Acme — AI Workflow Automation', 'Automate Your Workflows', 'Try Free'),
      descriptions('Connect your tools and automate in minutes. No code required.'),
      url('https://acme.dev'),
    ),
  })

Capabilities

Google Ads import

Pull campaigns, ad groups, keywords, RSA ads, sitelinks, and callouts from your live Google Ads account.

Meta Ads import

Import Meta campaigns, ad sets, and ads with the same command and the same TypeScript output format.

Clean code generation

Imported campaigns become idiomatic TypeScript using the SDK's typed helpers — not raw JSON or unreadable blobs.

Incremental import

Already managing some campaigns in code? Import only the ones you haven't touched yet.

Extensions included

Sitelinks, callout extensions, and structured snippets are imported alongside your campaigns.

Ready to modify

Imported files are fully editable. Change anything and run `ads apply` to push the update.