Skip to content

draft_campaign / update_campaign: campaign URL options - #116

Merged
kLOsk merged 1 commit into
kLOsk:mainfrom
xgp:feat/campaign-url-options
Oct 28, 2026
Merged

kLOsk merged 1 commit into
kLOsk:mainfrom
xgp:feat/campaign-url-options

Conversation

@xgp

@xgp xgp commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Closes #105.

Adds optional tracking_url_template, final_url_suffix and url_custom_parameters to draft_campaign and update_campaign, in the shape agreed on the issue. It's separate from #115 (location option), as you asked. The two touch the same functions, so whichever merges second needs a small rebase, and I'll do it.

Semantics

Value update_campaign draft_campaign
omitted (None) unchanged unset (Google's default)
"" / [] cleared; the preview names the removal nothing to clear, so it's left out of the plan
a value set; url_custom_parameters replaces the whole list set

Existing callers send exactly the same request as before, and a test pins that.

Validation

As you asked, it's kept light:

  • Template: must contain {lpurl}, {lpurl+2}, {lpurl+3}, {unescapedlpurl} or {escapedlpurl}. Case-insensitive.
  • Custom parameters:
    • each needs a key and a value;
    • keys can be up to 16 characters and values up to 250;
    • a leading _ on a key is dropped, because {_grp} in a template means key grp and people type the underscore.
  • Final URL suffix: a leading ? or & is stripped.

Everything else is left to the validate_only dry run.

Preview (update_campaign)

  • Current values: for each field given, changes holds current_<field> next to the new value, like current_daily_budget.
  • Removals: clearing a value that is set adds a warning, Removes the campaign's tracking_url_template (currently '…'). Clearing something already empty doesn't.
  • example_click:
    • It takes one of the campaign's ads' final URLs and shows landing_page_url (with the suffix) and tracking_url (the template with {lpurl} and {_key} filled in).
    • ValueTrack parameters such as {keyword} are left as they are. {lpurl} is shown as the bare final URL, because Google escapes it by position. The docstring says it's approximate; its job is to make a typo visible.
    • A campaign with no ads yet gets no example.
    • draft_campaign has no ads either, so it has no example.
  • Confirmation: a single confirmation.

Apply and dry run

  • Apply: the fields go on the campaign operation the tool already builds.
  • Clearing: on update, each field given has its own update_mask path, so an empty value under the mask clears it.
  • Dry run: the existing validate_only path.

I ran validate-only dry runs against a paused Search campaign in a live account:

  • a real UTM template with {adgroupid} and {keyword};
  • separately, a suffix plus a custom parameter.

Both came back DRY_RUN_SUCCESS with validated_calls: 1, and nothing was applied. The preview's example_click showed the expected URL.

Rules and tests

  • Rules: .cursor/rules/adloop.mdc now has the tool table entries and one bullet on the semantics and example_click. Synced with scripts/sync-rules.py.
  • Tests: tests/test_campaign_url_options.py (20 tests) covers:
    • every {lpurl} variant, a template without one, the key and value limits, and an invalid input refused before any read;
    • draft with the options omitted, empty and set;
    • the update preview's current values, example_click, removals and the no-ads case;
    • create, update and the clearing masks;
    • parameter descriptions on both tools.
  • Suite: uv run pytest gives 1683 passed, 2 skipped.

get_campaign_settings reads all three back. Docs left for you to regenerate after the release.

@kLOsk kLOsk left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. One fix before we merge: the {lpurl} check refuses {escapedlpurl+2} and {escapedlpurl+3}, which are valid ValueTrack parameters. Something like \{(un)?(escaped)?lpurl(\+[23])?\}, also used in _example_click_urls. Please also note in the tool description that example_click is approximate (ad group, ad or keyword templates override the campaign's), and say "alphanumeric, max 8" for custom parameter keys. After #115 lands this needs a rebase, sorry about the shared hunks.

Optional tracking_url_template, final_url_suffix and url_custom_parameters on both tools. Omitted leaves a value unchanged; an empty string or list clears it, and the preview names the removal. Validation stays light: {lpurl} or any variant ({lpurl+2}, {escapedlpurl+3}, ...) in the template, alphanumeric custom parameter keys of at most 8 characters, values up to 250; the validate_only dry run catches the rest. The update_campaign preview shows each current value and example_click, one of the campaign's final URLs with the campaign's options applied (approximate: lower-level templates override it).

Fixes kLOsk#105.
@xgp

xgp commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on main (after #115 and a6d492d) and updated:

  • Template check: the template check now uses one regex, \{(un)?(escaped)?lpurl(\+[23])?\}, case-insensitive. _example_click_urls fills every variant with the same regex. Tests cover {escapedlpurl+2}, {escapedlpurl+3} and {unescapedlpurl+2}, and check that look-alikes such as {lpurl+4} and {escaped_lpurl} are refused.
  • Custom parameter keys: must be alphanumeric, at most 8 characters. The tool descriptions and the rules now say so.
  • example_click: described as approximate in the tool description, the docstring and the rules, because ad group, ad and keyword templates override the campaign's.

uv run pytest: 1732 passed, 2 skipped. I also re-ran a validate-only dry run against a live paused campaign, setting the location option and the tracking template in one plan. It came back DRY_RUN_SUCCESS with one validated call.

@xgp
xgp force-pushed the feat/campaign-url-options branch from 10f0d06 to ebde590 Compare October 27, 2026 21:58
@kLOsk
kLOsk merged commit 44cd67e into kLOsk:main Oct 28, 2026
3 checks passed
@xgp

xgp commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for merging, and for the README update. #117 is rebased on top of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

update_campaign / draft_campaign: set campaign URL options (tracking template, final URL suffix, custom parameters)

2 participants