Skip to content

Building a Cowork Plugin for Google PPC Landing Pages

Overview

Launching a Google Paid Search landing page used to take us the better part of a day. Design had to match brand standards, forms needed to wire up to Act-On and SendGrid, GTM had to be configured correctly, UTM parameters needed to flow through to hidden fields for attribution, and every page required a mobile pass before it went anywhere near production. With multiple campaigns running simultaneously, the bottleneck was real.

We built a Claude Code plugin for our internal Cowork workspace that changes that equation. The plugin takes a campaign brief and outputs two artifacts: a content spec in Markdown and a production-ready scaffold HTML file with the full design system already baked in. Claude Code then applies a standardized checklist, serves the page locally for review, and prepares it for deployment. A new page now goes from brief to live at landing.goosedigital.com/{slug}/ in about an hour.

Approach

The plugin lives inside Cowork, our internal AI workspace built on Claude. When we start a new campaign, we feed it the campaign focus, target audience, key offer, and any specific trust signals (partner badges, regional copy). The plugin generates two outputs every time:

  • {slug}-spec.md — a content spec covering all copy, section structure, form configuration, image URLs, and Lead_Source value
  • {slug}-scaffold.html — a complete, self-contained HTML file with all CSS inline, all JS inline, and the full design system applied

The design system is fixed and baked into the scaffold: DM Sans for body text, DM Serif Display for italic heading emphasis, brand colors (#000018, #1863dc, #54B948, #F58025), a frosted-glass fixed header, alternating section backgrounds, and centered card layouts. There are no build tools, no frameworks, no external dependencies beyond Google Fonts and Font Awesome.

Once the scaffold lands in the repo, Claude Code runs through a pre-production checklist before anything is committed:

  • GTM snippet (GTM-NHTPB5) injected in <head> and as a noscript immediately after <body>
  • Favicon paths corrected to relative ../favicon-32x32.png and ../favicon-192x192.png
  • Logo paths corrected — ../goose-logo.png in the header (62px), remote inverted SVG in the footer for dark backgrounds
  • Font Awesome SRI hash verified on the CDN link
  • Form action confirmed as https://marketing.goosedigital.com/acton/forms/userSubmit.jsp
  • Form JS fires Act-On and /api/form-notify in parallel, not in sequence
  • showSuccess() redirects to /thank-you/ rather than showing an inline message
  • UTM fields auto-captured from URL into hidden inputs at page load
  • Regional trust badge — maple leaf + “Proudly Canadian Owned and Operated Since 2015” for Canadian campaigns; certificate badge + social proof count for US campaigns
  • Mobile pass — hero stacks, form accessible at 375px, hero CTA button visible on mobile only

The /api/form-notify Cloudflare Pages Function handles instant email alerts to [email protected] via SendGrid, with the lead’s email set as reply-to so the sales team can respond directly. The Lead_Source hidden field identifies the originating page across all form submissions.

Deployment is a git push. Cloudflare Pages auto-deploys in roughly 30 seconds, serving each page at landing.goosedigital.com/{slug}/ with no redirect rules needed.

Results

We have three campaigns live through this workflow:

  • HubSpot Canada PPClanding.goosedigital.com/hubspot-canada-ppc/
  • HubSpot USA PPClanding.goosedigital.com/hubspot-usa-ppc/
  • Salesforce Marketing Cloud Canada PPClanding.goosedigital.com/sfmc-services-canada-ppc/

The SFMC Canada page added a YouTube embed and a Salesforce Silver Partner badge, which required a CSP update in public/_headers and sandbox attributes on the iframe. Both were handled in the checklist pass without any manual back-and-forth.

End-to-end time from brief to live is consistently around one hour, down from a half-day or more. The checklist approach has eliminated the class of errors we used to catch in QA — mismatched form actions, missing GTM containers, broken favicon paths — because Claude Code flags and fixes them before the first local preview.

Attribution is clean. Every UTM parameter flows from the Google Ads URL through the hidden fields into Act-On, and every lead triggers an immediate email notification with the source page identified.

Lessons Learned

  1. A fixed design system is a prerequisite for this kind of automation. The plugin works because the visual and structural rules are fully locked in. If the design were fluid, every scaffold would require design judgment and the automation would break down. Define the system first, then build the plugin around it.

  2. The checklist is as important as the scaffold. The scaffold generates correct-looking output most of the time, but edge cases — new CDN links needing SRI hashes, YouTube embeds needing CSP changes, regional variants needing different trust signals — require a deterministic review pass. Encoding that pass as a Claude Code checklist means it runs every time without relying on memory.

  3. Parallel form submissions are worth the extra JS. Firing Act-On and SendGrid in parallel rather than sequentially means a slow Act-On response doesn’t delay the sales notification. We’ve seen Act-On take several seconds on occasion; the parallel approach keeps notification latency under one second regardless.

  4. Self-contained HTML files age better than you’d expect. No build tools means no dependency rot, no Node version conflicts, no broken pipelines six months later. Each page is exactly what it is. That simplicity is a feature, not a limitation.

  5. Cloudflare Pages Functions are the right scope for notification logic. Keeping form-notify.js as a shared function across all pages — rather than per-page JS — means improvements (HTML escaping, error handling, new fields) apply everywhere at once. The Lead_Source hidden field does all the routing work.