Improve one existing campaign at a time: diagnose, propose a short plan, perform the changes the user approves. Pre-campaign inputs belong to Get AI Campaign Suggestions; plain reporting to Query Campaign Performance Analytics.
Base URL https://www.wixapis.com/_serverless/pa-google unless shown in full; the paths below include their version. <AUTH> is the Authorization header; body calls also need Content-Type: application/json. Amounts are in micros (1,000,000 = 1 unit of the account currency, read from GET /v1/accounts/current-site).
campaignType: "SMART" → the first thing you say is the Performance Max Leads offer (see Smart campaigns); no diagnosis and no call before it, unless the user already declined.GET /v1/campaigns/{id} right before an approved update, because the update sends the whole entity. For a pasted campaign that re-read is the first call you make; if it returns CAMPAIGN_NOT_FOUND, the campaign is not on the current site: ask the user which site or campaign to apply the change to, and apply nothing until a re-read succeeds.Calls run on the current site from the call context; ask which site only when none is selected, and never list sites to hunt for a campaign.
GET /v1/campaigns once; it returns full campaign objects. Read id, name, campaignType, status, resourceName, createdDate, actionDate, budget.amountMicros.DRAFT campaigns (nothing serves yet). One non-draft campaign left → proceed; several → list them one line each and ask. Mention a draft in one line; if the user explicitly wants to improve a draft, offer to add assets when there are few and to add search themes, otherwise point to launching it (Manage Campaign Lifecycle).Days running = days since actionDate (last launch or resume), else since createdDate. A statement from the user about the campaign's age ("just created", "still learning", "running for a month") overrides the dates: use it, do not recompute or dispute it.
Status other than LIVE or LEARNING: name the blocking action first, then continue with the row for the campaign's type. PAUSED → resume first (Manage Campaign Lifecycle); IN_REVIEW → wait for review; DISAPPROVED → fix the policy issue; NOT_SERVING → billing; ENDED/ERROR → stop here and offer a new campaign.
| Campaign | Sources |
|---|---|
PERFORMANCE_MAX_LEADS, under 14 days (or the user says it is new or still learning) | Success guide only; no recommendations or analytics calls. Say performance-based advice starts after about two weeks. Discourage edits during learning except adding search themes (which the guide itself raises); if the user insists, warn that an edit resets Google's learning, then proceed |
PERFORMANCE_MAX_LEADS, 14 days or more | Recommendations + analytics. Do not retrieve the guide for advice (reading it to mark or reopen an item is still fine). While status is LEARNING (about 28 days), say the data is usable but early |
PERFORMANCE_MAX (general or retail) | Recommendations + analytics; add shopping performance when performanceMaxCampaign.feedLabel is set |
SMART | Offer the Performance Max Leads upgrade first (below); if declined, run the Smart path |
The guide scans the landing page, the campaign configuration and the site's Google connections; it never uses metrics, so LEARNING and empty analytics do not block it. A request to improve the campaign or see the guide is approval to retrieve it. platformType is always GOOGLE.
Response: { "campaignSuccessGuide": { "id", "url" (landing page), "suggestions": [ { "id", "type", "status" } ] } }. The first call can take 120 seconds; wait, do not retry. Later calls return the saved guide at any campaign age, unless the landing page URL changed. suggestions is in priority order and lists only items that need attention; OPEN = pending, COMPLETED = the user marked it done (nothing was changed for them). Show OPEN items three at a time in API order, hide COMPLETED ones, and invite the next batch when more remain.
| Types | What to offer |
|---|---|
GOOGLE_ADS_SEARCH_THEMES | Generate a set with POST /v1/search-theme-suggestions and { "landingPageUrl": "<performanceMaxCampaign.url>", "textSuggestionInfo": { "languageCode": "<languages[0].languageCode>" } } → searchThemes[], each becoming { "searchTheme": { "text": "…" } }; show it, apply the approved set with the update below. Link the Keywords Manager (Google Ads Dashboard Navigation) only if the user prefers the manual route |
CONVERSION_POINT (no visible lead form or booking action), HEADER_MATCH (page heading does not match the ad headlines), CONTACT_AND_CREDIBILITY (no visible phone and email), CLEAR_CTA_COPY, ABOVE_THE_FOLD_CTA, MINIMIZE_FORM_FIELDS (over 4 fields), TESTIMONIAL, SOCIAL_CHANNELS, GOOGLE_REVIEWS, FAQ_SECTION | Landing-page content: describe the edit in one line, offer to draft copy after approval; the user applies it in the Editor |
GOOGLE_BUSINESS_PROFILE_CONNECTION | Offer to start Connect a Wix Site to Google Business Profile; the owner finishes Google's consent in the browser |
GOOGLE_MERCHANT_CENTER_CONNECTION | Read account.merchantCenterAccountId from GET /v1/accounts/current-site; ask for the ID if absent; update the account per Install Google Ads and Create an Account. The link starts PENDING |
MOBILE_OPTIMIZATION, SITE_SPEED | Offer to inspect and name a concrete cause before promising anything; the user applies the site change |
Editor link: use editUrl from the site context; if absent, make one Query Sites lookup filtered by id.$in with the current site ID; otherwise write Go to the Editor as plain text. One Editor link per answer, never guessed.
Mark done or reopen: retrieve the guide first (works at any age), confirm the type is present and read its current status, then update by type. A clear "I did X" is approval, no extra confirmation. The response wraps the updated guide; "status": "OPEN" reopens. Completion is self-reported: never say the page or campaign changed.
Google generates these from the account's settings and recent performance and regenerates them on its own schedule, so an item can keep appearing after you act on it; say so. Only types the user can act on through Wix are returned. details is Google's payload for the type, read as is; impact is Google's forecast, not a promise (convert costMicros with the account currency). An empty list is a finding, not an error: fall through to the performance diagnosis.
type | Act through |
|---|---|
CAMPAIGN_BUDGET, FORECASTING_CAMPAIGN_BUDGET, MARGINAL_ROI_CAMPAIGN_BUDGET | Daily budget (update below), proposing the option from details.budgetOptions with its impact |
IMPROVE_PERFORMANCE_MAX_AD_STRENGTH | Leads: add the field types and counts in details.assetCoverage.adStrengthActionItems (a Wix addition, already filtered to the text and image types the update accepts). Other Performance Max campaigns: describe it and offer no asset edit, the update ignores their assets |
PERFORMANCE_MAX_FINAL_URL_OPT_IN | Set performanceMaxCampaign.assetAutomationSettings to [{ "type": "FINAL_URL_EXPANSION_TEXT_ASSET_AUTOMATION", "status": "OPTED_IN" }] |
CALL_ASSET | Set performanceMaxCampaign.phone (countryCode, phoneNumber) |
SHOPPING_* (disapproved products, Merchant Center suspension, missing GTIN, color, size…) | Not fixable through the Google Ads APIs: summarize details (merchant, product counts) and link the Stores products page (Stores Dashboard Navigation) and Google Merchant Center |
PERFORMANCE_MAX_OPT_IN (account-level, empty campaignIds) | Create a Performance Max Leads campaign with Create and Launch a Performance Max Campaign |
A type not listed here: describe it from Google's name and offer no action.
Use the analytics calls that fit the question; do not invent thresholds. Bodies and enums are in Query Campaign Performance Analytics. The minimal diagnosis is one POST /v1/performance-metrics call, keyed by campaignResourceName (the campaign's resourceName), with an explicit 30-day dateRange.custom (from/to, YYYY-MM-DD) and includePreviousPeriod: true; the previous-period comparison needs that finite range, an omitted range (campaign lifetime) fails. Add others only when the question needs them: POST /v1/conversion-metrics (leads, orders, cost per lead; dateRange is required), POST /v2/search-term-metrics (sort by COST: terms that spend without converting are exclusion candidates, judged for relevance to the business) and POST /v1/asset-performance-metrics (Leads only; performanceLabel is LOW, GOOD or EXCELLENT once an asset leaves LEARNING: a LOW asset is a replacement candidate) take campaignId. Summarize in two to four lines; every proposal cites the number behind it.
Offer the upgrade first, before any diagnosis or API call, unless the user has already declined it; two sentences, never forced, ending with the question of which way to go. Stop there: the Smart plan below comes only after the user declines, never in the same message as the offer. The reasons: Performance Max Leads is Google's recommended path from Smart campaigns, and it serves across all Google surfaces (Search, Display, YouTube, Gmail, Discover, Maps) rather than Search alone. If accepted, follow Create and Launch a Performance Max Campaign, keep the Smart campaign running until the new one is launched, then offer to pause it (five live campaigns per site, and double spend otherwise). Google issues no recommendations for Smart campaigns, so if the user keeps theirs, diagnose with analytics. Exclude clearly irrelevant search terms that spend under any focus; then, when the user states no goal, pick the focus with these rules of thumb (what they asked for, such as "more leads" or "spending too much", wins):
Propose first, change only on approval (see Order of operations): present the plan → the user picks items → generate what is needed and show it → re-read the campaign → show only what changes (field, before, after; never the whole entity) → one explicit yes → one update → confirm from the response.
Every update sends the whole campaign; never send a partial body. PATCH /v1/campaigns/{id} takes the entire entity returned by Get Campaign with only the changed fields different; the fields to update are inferred, updateMask is ignored, and omitted fields may be cleared. To add a list item (asset, search theme, excluded term) append it without a resourceName; to remove one, omit it. Keep id, accountId, campaignType, locations, languages, phone, and every existing asset and signal you are not removing. The same rule governs every update in Manage Campaign Lifecycle; field-level examples: Update Campaign.
The response is { "campaign": { … } } with the saved state; confirm the change from it.
| Change | Field (type) | Rules |
|---|---|---|
| Daily budget | budget.amountMicros (any) | Source, in order: Google's budgetOptions; POST /v1/budget-recommendation (Performance Max) or POST /v1/budget-suggestions (Smart), bodies in Get AI Campaign Suggestions; last resort about 1.5× the current budget. Always within GET /v1/campaign/daily-budget-boundaries |
| Assets | performanceMaxCampaign.assetGroups[0].assetGroupAssets.assets[] (Leads only; retail asset edits are ignored) | Ask whether to generate images or use Media Manager URLs the user supplies. Generate with POST /v1/text-asset-suggestions and POST /v1/image-asset-suggestions (60 to 120 s; images are saved to the Media Manager). Per-asset shape and the count table (headlines 3–15, descriptions 2–5, images 1–20 per type, logos 1–5) are in Create and Launch a Performance Max Campaign; the update also accepts PORTRAIT_MARKETING_IMAGE (4) and LANDSCAPE_LOGO (4), 0–20 each; max 120 assets, no duplicates. Offer removing LOW-labelled assets as a separate optional item, keeping the minimums |
| Search themes | assetGroups[0].assetGroupSignals.signals[].searchTheme.text (Leads) | Max 25 |
| Excluded search terms | smartCampaign.excludedSearchTerms[] (Smart); performanceMaxCampaign.excludedKeywords[] (Leads) | { "freeFormKeywordTheme": "…", "displayName": "…" } appended to the existing list |
| Keyword themes, ad copy, landing page | smartCampaign.keywordThemes[] (max 10, same shape as excluded terms), smartCampaign.adGroups[0].ads[0].headlines (3, ≤30 chars) and .descriptions (2, ≤90), smartCampaign.url (Smart) | Landing page must be a published page of the site. For a Leads campaign, changing performanceMaxCampaign.url resets learning and the guide: warn, and change it only if the user insists |
| Locations | locations[] (any) | geoTargetConstants/{id} from GET /v1/geo-options |
Plain Markdown, top to bottom; no tables or columns in the user-facing answer.
| Error | Response |
|---|---|
ACCOUNT_NOT_FOUND, CAMPAIGN_NOT_FOUND, CAMPAIGN_DAILY_BUDGET_TOO_HIGH, MAXIMUM_NUMBER_OF_CAMPAIGNS_REACHED | As in Manage Campaign Lifecycle; never probe other sites to recover. On the re-read of a pasted campaign, CAMPAIGN_NOT_FOUND means it is not on the current site: ask which site or campaign before applying anything |
CAMPAIGN_TYPE_NOT_SUPPORTED, PLATFORM_NOT_SUPPORTED | Guides exist only for Performance Max Leads with platformType: "GOOGLE"; use the recommendations path |
SUGGESTION_NOT_FOUND | Retrieve the guide and use a type it contains |
INVALID_ASSET_GROUP_ASSETS, NOT_ENOUGH_ASSETS, DUPLICATE_ASSET, INVALID_IMAGE_FORMAT | The resulting asset list breaks a count, size or uniqueness rule; fix and resend the full entity |
| Timeout on the guide or asset generation; permission error | Report the unknown outcome and retry later, never a second scan immediately; after a rejected call stop, do not try other base URLs or sites |
Last updated: 9 November 2026