{"id":51621400,"url":"https://github.com/httpdss/terraform-provider-googleads","last_synced_at":"2026-07-12T20:30:46.866Z","repository":{"id":363195806,"uuid":"1262187981","full_name":"httpdss/terraform-provider-googleads","owner":"httpdss","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-07T20:20:26.000Z","size":58,"stargazers_count":0,"open_issues_count":27,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T22:20:52.333Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/httpdss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-07T17:25:34.000Z","updated_at":"2026-06-07T20:20:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/httpdss/terraform-provider-googleads","commit_stats":null,"previous_names":["httpdss/terraform-provider-googleads"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/httpdss/terraform-provider-googleads","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httpdss%2Fterraform-provider-googleads","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httpdss%2Fterraform-provider-googleads/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httpdss%2Fterraform-provider-googleads/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httpdss%2Fterraform-provider-googleads/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/httpdss","download_url":"https://codeload.github.com/httpdss/terraform-provider-googleads/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httpdss%2Fterraform-provider-googleads/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35402741,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-12T02:00:06.386Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-12T20:30:45.937Z","updated_at":"2026-07-12T20:30:46.861Z","avatar_url":"https://github.com/httpdss.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Terraform Provider for Google Ads\n\n`terraform-provider-googleads` is a Terraform Plugin Framework provider for managing practical Google Ads Search campaign structures as code.\n\nThis first version uses the Google Ads REST API directly instead of the official generated Go client. The Google Ads API is exposed as stable REST endpoints, and the provider only needs OAuth2 plus a small set of mutate/search operations. Direct REST keeps the initial provider small, readable, and easy to audit while still using official Google Ads API resource names, services, GAQL reads, and mutate semantics.\n\n## Supported resources\n\n- `googleads_campaign_budget`\n- `googleads_campaign`\n- `googleads_ad_group`\n- `googleads_ad_group_keyword`\n- `googleads_ad_group_ad` for responsive search ads\n- `googleads_campaign_criterion` for location and language criteria\n\nEach resource stores the Google Ads `resource_name` as the stable Terraform `id` and exposes it as `resource_name` for references.\n\n## Provider configuration\n\nArguments can be set directly in Terraform or through environment variables:\n\n- `developer_token` / `GOOGLEADS_DEVELOPER_TOKEN` *(sensitive)*\n- `customer_id` / `GOOGLEADS_CUSTOMER_ID`\n- `login_customer_id` / `GOOGLEADS_LOGIN_CUSTOMER_ID`\n- `client_id` / `GOOGLEADS_CLIENT_ID` *(sensitive)*\n- `client_secret` / `GOOGLEADS_CLIENT_SECRET` *(sensitive)*\n- `refresh_token` / `GOOGLEADS_REFRESH_TOKEN` *(sensitive)*\n- `token_file` / `GOOGLEADS_TOKEN_FILE`\n- `credentials_file` / `GOOGLEADS_CREDENTIALS_FILE`\n- `api_version` / `GOOGLEADS_API_VERSION` defaults to `v23`\n- `validate_only` / `GOOGLEADS_VALIDATE_ONLY`\n\nYou can authenticate either with:\n\n1. `credentials_file` plus `token_file`; or\n2. `credentials_file` plus `refresh_token`; or\n3. `client_id`, `client_secret`, and `refresh_token`.\n\nSecrets are marked sensitive in the Terraform schema and are not logged by the provider.\n\n## Normalization rules\n\nThe provider normalizes equivalent Google Ads inputs to avoid unnecessary Terraform diffs:\n\n- `customer_id` and `login_customer_id` may be set with or without dashes. They are sent to Google Ads without dashes.\n- Enum-like fields such as `status`, `delivery_method`, `advertising_channel_type`, `bidding_strategy_type`, `type`, and `match_type` are normalized to uppercase snake case. For example, `manual-cpc` becomes `MANUAL_CPC`.\n- Google Ads resource references may be full resource names such as `customers/1234567890/campaigns/111`. If a full resource name contains a dashed customer ID, the customer segment is normalized.\n- For customer-scoped references such as `campaign_budget`, `campaign`, and `ad_group`, numeric IDs and collection-relative IDs are accepted in CRUD calls and expanded with the configured `customer_id` where safe. Examples: `111` or `campaigns/111` becomes `customers/\u003ccustomer_id\u003e/campaigns/111`.\n- For campaign criterion constants, numeric IDs are accepted: `2840` becomes `geoTargetConstants/2840`, and `1000` becomes `languageConstants/1000`.\n- Imported resources still use full Google Ads resource names. After a resource has state, numeric or collection-relative references that point at the same remote object are planned as the canonical resource name to suppress equivalent diffs.\n\n## Validation rules\n\nTerraform validates common mistakes before calling the Google Ads API:\n\n- Enum-like fields reject unsupported values with a message listing the accepted values. Hyphenated/lowercase input is accepted when it normalizes to a supported Google Ads enum value.\n- Campaign `start_date` and `end_date` must use `YYYY-MM-DD`.\n- `bidding_strategy_type = \"TARGET_CPA\"` requires positive `target_cpa_micros`.\n- `bidding_strategy_type = \"TARGET_ROAS\"` requires positive `target_roas`.\n- `googleads_campaign_criterion.type = \"LOCATION\"` requires `location_geo_target_constant`.\n- `googleads_campaign_criterion.type = \"LANGUAGE\"` requires `language_constant`.\n- Responsive search ads require 3-15 headlines and 2-4 descriptions. Headlines must be 30 characters or fewer; descriptions must be 90 characters or fewer.\n\n## Google Ads API access\n\n1. Create or choose a Google Cloud project.\n2. Enable the Google Ads API for that project.\n3. Configure an OAuth consent screen.\n4. Create OAuth client credentials. A Desktop app client is easiest for the local helper flow.\n5. Download the OAuth client credentials JSON as `credentials.json`.\n6. In Google Ads, request or locate your developer token under **Tools \u0026 Settings → Setup → API Center**.\n7. Use a Google Ads customer ID without dashes, for example `1234567890`. If you use a manager account, set `login_customer_id` to the manager account ID.\n\n## Generate a refresh token\n\nBuild and run the helper CLI:\n\n```bash\ngo build -o bin/googleads-auth ./cmd/googleads-auth\n./bin/googleads-auth -credentials ./credentials.json -out ./token.json\n```\n\nThe helper prints a browser URL, asks you to paste the authorization code, saves `token.json`, and prints provider environment variables. The saved token JSON contains a refresh token, so keep it private.\n\n## Install local provider\n\n```bash\nmake install-local VERSION=0.1.0 OS_ARCH=linux_amd64\n```\n\nThis installs the provider at:\n\n```text\n~/.terraform.d/plugins/registry.terraform.io/local/googleads/0.1.0/linux_amd64/terraform-provider-googleads_v0.1.0\n```\n\nAdjust `OS_ARCH` for your platform if needed, for example `darwin_arm64`.\n\n## Example Terraform\n\n```hcl\nterraform {\n  required_providers {\n    googleads = {\n      source  = \"local/googleads\"\n      version = \"0.1.0\"\n    }\n  }\n}\n\nprovider \"googleads\" {\n  developer_token   = var.googleads_developer_token\n  customer_id       = var.googleads_customer_id\n  login_customer_id = var.googleads_login_customer_id\n\n  credentials_file = \"./credentials.json\"\n  token_file       = \"./token.json\"\n\n  validate_only = false\n}\n\nresource \"googleads_campaign_budget\" \"search_budget\" {\n  name          = \"terraform-search-budget\"\n  amount_micros = 5000000\n}\n\nresource \"googleads_campaign\" \"search\" {\n  name                     = \"terraform-search-campaign\"\n  advertising_channel_type = \"SEARCH\"\n  status                   = \"PAUSED\"\n  campaign_budget          = googleads_campaign_budget.search_budget.resource_name\n\n  start_date = \"2026-07-01\"\n  end_date   = \"2026-12-31\"\n\n  bidding_strategy_type = \"MANUAL_CPC\"\n\n  network_settings = {\n    target_google_search          = true\n    target_search_network         = true\n    target_content_network        = false\n    target_partner_search_network = false\n  }\n}\n\nresource \"googleads_campaign_criterion\" \"us\" {\n  campaign                     = googleads_campaign.search.resource_name\n  type                         = \"LOCATION\"\n  location_geo_target_constant = \"geoTargetConstants/2840\"\n}\n\nresource \"googleads_campaign_criterion\" \"english\" {\n  campaign          = googleads_campaign.search.resource_name\n  type              = \"LANGUAGE\"\n  language_constant = \"languageConstants/1000\"\n}\n\nresource \"googleads_ad_group\" \"main\" {\n  campaign       = googleads_campaign.search.resource_name\n  name           = \"terraform-main-ad-group\"\n  status         = \"PAUSED\"\n  type           = \"SEARCH_STANDARD\"\n  cpc_bid_micros = 1000000\n}\n\nresource \"googleads_ad_group_keyword\" \"keyword\" {\n  ad_group   = googleads_ad_group.main.resource_name\n  text       = \"terraform devops automation\"\n  match_type = \"PHRASE\"\n  status     = \"ENABLED\"\n}\n\nresource \"googleads_ad_group_ad\" \"rsa\" {\n  ad_group = googleads_ad_group.main.resource_name\n  status   = \"PAUSED\"\n\n  final_urls = [\"https://example.com\"]\n\n  path1 = \"devops\"\n  path2 = \"automation\"\n\n  responsive_search_ad = {\n    headlines = [\n      \"Automate DevOps Workflows\",\n      \"Terraform Managed Campaigns\",\n      \"Reliable Infra Automation\",\n    ]\n\n    descriptions = [\n      \"Create and manage your campaigns as code.\",\n      \"Use Terraform workflows for repeatable Google Ads setup.\",\n    ]\n  }\n}\n```\n\nA copy of this example is in `examples/search_campaign`.\n\n## Run Terraform\n\n```bash\ncd examples/search_campaign\nterraform init\nterraform plan\nterraform apply\nterraform destroy\n```\n\nFor a dry API validation without creating resources, set:\n\n```bash\nexport GOOGLEADS_VALIDATE_ONLY=true\n```\n\nor set `validate_only = true` in the provider block.\n\n## API diagnostics\n\nWhen Google Ads API calls fail, the provider parses `GoogleAdsFailure` details from REST responses and surfaces actionable Terraform diagnostics including the Google Ads error code, message, trigger, field path, and operation index when available. Request credentials and token values are not included in diagnostics.\n\n## Retry behavior\n\nGoogle Ads API requests are retried conservatively for transient failures: HTTP `429`, HTTP `5xx`, and Google Ads statuses `RESOURCE_EXHAUSTED`, `UNAVAILABLE`, and `DEADLINE_EXCEEDED` when identifiable from an error response. The provider makes up to 3 attempts total with exponential backoff, jitter, and a maximum delay of 2 seconds. Validation and business-rule errors such as `INVALID_ARGUMENT` are not retried.\n\n## Delete behavior\n\nGoogle Ads resources are generally removed through each service's `remove` operation rather than physically deleted from historical reporting. The provider uses remove operations for campaign budgets, campaigns, ad groups, ad group criteria, ad group ads, and campaign criteria. Removed resources may remain visible in Google Ads history/reporting, but Terraform removes them from state after a successful destroy.\n\n## Imports\n\nResources can be imported by full Google Ads resource name. After importing, run `terraform plan` and update your configuration to match any remote-only values Terraform reads back from Google Ads.\n\n```bash\nterraform import googleads_campaign_budget.search_budget customers/1234567890/campaignBudgets/222\nterraform import googleads_campaign.search customers/1234567890/campaigns/111\nterraform import googleads_ad_group.main customers/1234567890/adGroups/333\nterraform import googleads_ad_group_keyword.keyword customers/1234567890/adGroupCriteria/333~444\nterraform import googleads_ad_group_ad.rsa customers/1234567890/adGroupAds/333~555\nterraform import googleads_campaign_criterion.us customers/1234567890/campaignCriteria/111~2840\n```\n\nImport notes:\n\n- `googleads_ad_group_ad` reads back required RSA fields including `final_urls`, `path1`, `path2`, `headlines`, and `descriptions` so imported ads can be represented in Terraform configuration.\n- `googleads_campaign_criterion` supports imported location and language criteria in this first version.\n- Google Ads resource names are account-scoped; import with the same `customer_id` and optional `login_customer_id` used by the provider.\n\n## Development\n\n```bash\nmake fmt\nmake test\nmake build\n```\n\nAcceptance tests are structured but disabled by default because they require real Google Ads credentials and can mutate an account:\n\n```bash\nTF_ACC=1 \\\nGOOGLEADS_DEVELOPER_TOKEN=... \\\nGOOGLEADS_CUSTOMER_ID=... \\\nGOOGLEADS_CREDENTIALS_FILE=./credentials.json \\\nGOOGLEADS_TOKEN_FILE=./token.json \\\ngo test ./internal/provider -run TestAcc\n```\n\n## Notes and current limitations\n\n- The initial provider focuses on Search campaign setup.\n- Responsive search ads are the first supported ad type.\n- Conversion actions are not implemented in this first pass; add them as a follow-up `googleads_conversion_action` resource using `ConversionActionService`.\n- GAQL reads are used through `GoogleAdsService.Search`; writes use resource-specific mutate endpoints.\n- Partial failures are disabled so Terraform receives clear all-or-nothing API failures.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttpdss%2Fterraform-provider-googleads","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhttpdss%2Fterraform-provider-googleads","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttpdss%2Fterraform-provider-googleads/lists"}