rsa-refresh
Skill72 starsChanged 4 months agoMITView on GitHub
Refresh RSA ad copy by scraping the business website, identifying LOW-performing assets, and generating replacement headlines and descriptions using AI. Auto-invoke when user says 'refresh RSAs for [account]', 'update RSA assets', 'rewrite RSAs', or 'replace low-performing RSA assets'. Uses Firecrawl for scraping and Claude for copy generation.
- Reads credentials
- Installs packages
In this repository41 other files it gives its agents.
- account-diagnosticSkill
- ad-copy-generation-frameworkSkill
- ad-copy-verification-standardSkill
- add-account-negative-keywordsSkill
- ads-checkerSkill
- budget-guardianSkill
- budget-recommendation-calculatorSkill
- change-history-checkerSkill
- client-communication-standardsSkill
- competitor-analysis-v2Skill
- conversion-tracking-healthSkill
- dgen-automation-disableSkill
- fair-housing-complianceSkill
- ga4-campaign-cross-referenceSkill
- ga4-cross-analysisSkill
- ga4-lead-quality-investigationSkill
- gaql-query-patternsSkill
- geo-conflict-analyzerSkill
- google-ads-api-setupSkill
- google-ads-querySkill
- google-ads-samplesSkill
- impression-share-diagnosticsSkill
- investigation-methodologySkill
- lead-quality-pattern-analysisSkill
- lead-quality-recommendation-prioritizationSkill
- markdown-to-sheets-presenterSkill
- mcc-hack-auditSkill
- mutation-safetySkill
- neg-conflict-finderSkill
- non-serving-keyword-scannerSkill
- pmax-asset-automationSkill
- pmax-builderSkill
- portfolio-health-prioritizationSkill
- portfolio-pacing-rulesSkill
- rsa-bulk-editSkill
- rsa-single-accountSkill
- shared-budget-updaterSkill
- sqr-classifierSkill
- sqr-pipelineSkill
- underspending-investigationSkill
- youtube-placement-auditSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 0 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 40
Read rsa_context_{cid}.json and generate replacement headlines + descriptions following the reference docs:
- Very specific: line 75
Review the Refreshed tab against
rules.md: before any import: Validation Status N/A is the normal public default. - Very specific: line 196
Read-only against Google Ads — the scripts run GAQL SELECT queries and write only to the review sheet you own.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
RSA Refresh Skill
Refreshes Responsive Search Ad copy for one account by replacing
low-performing assets with new headlines and descriptions verified against
the actual business website. One operator (or agent) owns the workflow end
to end: prepare context → make the refresh-vs-rebuild call
(rules.md) → generate copy under the reference standards →
merge to a review sheet → review → import via Google Ads Editor.
The core rule at every step: Empty > Inaccurate — no slot ever carries a claim the website doesn't verify.
Workflow
Stage 1: Prepare Context
python scripts/rsa_refresh_generator.py \
--cid YOUR_CID \
--sheet-id YOUR_SHEET_ID \
--prepare-for-claudeThis will:
- Query existing RSAs and asset performance labels (BEST/GOOD/LOW/LEARNING)
- Scrape the business website using Firecrawl (with fallbacks)
- Extract basic property/business info
- Output
rsa_context_{cid}.jsonwith all data Stage 2 needs
Before generating anything, read the context per rules.md: check
features.scrape_failed (Stage 1 writes the JSON even when the scrape
failed — generating from an empty website_text is forbidden), then make
the refresh-vs-rebuild call from the label spread.
Stage 2: Generate Copy (Claude Code)
Read rsa_context_{cid}.json and generate replacement headlines +
descriptions following the reference docs:
references/pm-headline-structure.md-- 15 headline rules (1 customizer + 14 AI-generated)references/description-voice-lifting.md-- 3 descriptions with voice lifting techniquereferences/hallucination-filter.md-- Defense-in-depth filter for unverified claims (NOT embedded in the context JSON — load it from this folder)
Save output as copy_{cid}.json with format:
{
"headlines": {"AD_ID_1": ["H1", "H2", ...], "AD_ID_2": [...]},
"descriptions": ["D1", "D2", "D3"]
}In refresh mode, re-include every existing headline worth keeping — the
script mechanically preserves customizer assets only; anything else
survives by being in this file (rules.md owns that call).
Stage 3: Resume and Write to Sheet
python scripts/rsa_refresh_generator.py \
--cid YOUR_CID \
--sheet-id YOUR_SHEET_ID \
--copy-file copy_YOUR_CID.jsonThis merges the generated copy with the live ad structure and writes
"Original RSAs" and "Refreshed RSAs" tabs. Append is the default write
mode — add --clear when re-running the same account. Review in the
sheet before importing to Google Ads Editor. Exact merge gates (30/90
length, dedupe, the below-10-headlines skip) and both tabs' column layouts:
references/refresh-contract.md.
After the run — operator duties
- Review the Refreshed tab against
rules.mdbefore any import: Validation StatusN/Ais the normal public default;Changes Madeis the merge's log; ad groups missing from both tabs were skipped (console[SKIP]lines — below 10 headlines). - Rule out the false alarms — all-
NO_DATAlabels, error rows on a resume, doubled rows, the wrong-site scrape — per the table inrules.mdbefore reacting to any of them. - Import via Google Ads Editor — the sheet is a review queue; the import is always the human's move.
- Measure: re-run the baseline after the new copy has served ~30 days
and read the two
RSA Baselinerows side by side.
What this skill deliberately does NOT do
- No mutations. Output is a review sheet; the only write path into Google Ads is you importing through Editor.
- No autonomous copy. The script refuses to generate copy itself (direct automated mode raises with instructions to use the handoff) — Stage 2 is an agent applying the reference standards, and there is no flag that bypasses it.
- No mechanical preservation beyond customizers. BEST/GOOD assets survive a refresh because Stage 2 re-includes them, not because the script protects them.
- No after-measurement. The baseline captures before; the comparison is a later re-capture read side by side — no diffing logic ships.
- No multi-account batching. One
--cidper run (append mode is how runs accumulate into one sheet). For literal text swaps across many accounts at once, that'srsa-bulk-edit. - No out-of-the-box verticals beyond property management. The references and helpers are PM-tuned; adapting is a deliberate step (see Vertical Note).
Files in this skill
| File | Purpose |
SKILL.md | This file — the three-stage workflow + routing |
README.md | Zero-context setup: install, prerequisites, first run |
rules.md | Judgment layer: refresh-vs-rebuild, baseline reading, false alarms, escalation |
examples.md | Worked reads: a surgical refresh, the prepare-mode scrape trap, the baseline zeros misread |
references/refresh-contract.md | Exact mechanics: selection, file formats, merge gates, sheet + baseline contracts, enrichment gating |
references/pm-headline-structure.md | The 15-headline standard (embedded into the context JSON at Stage 1) |
references/description-voice-lifting.md | The 3-description standard + voice lifting (embedded at Stage 1) |
references/hallucination-filter.md | Forbidden-claim filter applied at Stage 2 (loaded from this folder) |
scripts/rsa_refresh_generator.py | Stages 1 and 3: queries, scrape, context/merge, sheet write |
scripts/rsa_baseline_snapshot.py | Pre-refresh metrics capture (standalone or via --baseline-sheet-id) |
rsa_context_{cid}.json and copy_{cid}.json are runtime artifacts in
your working directory — never part of the skill folder.
When to load a sibling skill
| Situation | Load |
| The account needs a ground-up RSA set — no salvageable copy, a new account, or you want the shipped SERP competitor analysis + GBP review pipeline | rsa-single-account |
| The change is a uniform literal text swap across existing ads (rebrand, spelling, customizer retirement) — no copy judgment | rsa-bulk-edit |
| Always at Stage 2, before any claim lands in the copy file | ad-copy-verification-standard |
| Stage-2 copywriting craft beyond the PM structure (the 23-element framework) | ad-copy-generation-framework |
| The baseline raises account-wide questions (Quality Score, structure, conversions) | account-diagnostic |
| Reading baseline impression-share movement (Search IS, lost-to-rank/budget) | impression-share-diagnostics |
No google-ads.yaml yet, or a 403 on the sheet write | google-ads-api-setup |
Prerequisites
google-ads.yamlat project root (Google Ads API credentials) — see the google-ads-api-setup skill if you don't have onetoken-sheets.jsonat project root OR a refresh token ingoogle-ads.yamlwith the spreadsheets scope (the setup skill's generator grantsspreadsheets+drive.readonlyby default — token predates that? re-run the generator once)FIRECRAWL_API_KEYenvironment variable (set in.envor shell — get a key at firecrawl.dev)pip install google-ads gspread google-auth pyyaml python-dotenv firecrawl-py requests beautifulsoup4 playwright
Override paths if needed:
--config path/to/google-ads.yaml --sheets-token path/to/token-sheets.jsonOptional: Pre-Refresh Baseline
python scripts/rsa_baseline_snapshot.py \
--cid YOUR_CID \
--account-name "Account Display Name" \
--sheet-id YOUR_SHEET_IDCaptures IWQS, QS components, ad metrics, and impression share before making changes so you can measure improvement afterward. Writes one dated row per capture to an "RSA Baseline" tab.
You can also have the generator capture the baseline automatically by adding
--baseline-sheet-id YOUR_SHEET_ID to Stage 1 — prefer this: the
integrated capture also fills the asset-label counts, which a standalone run
always writes as 0 (contract §baseline; rules.md has the misread).
Vertical Note
The reference docs under references/ are tuned for property management
(apartment / rental) accounts, and the headline/description references are
embedded into the context JSON at Stage 1 — they are the operative standard.
To adapt for another vertical:
- Replace the three files under
references/with your own headline structure, voice guide, and hallucination filter — this alone changes what Stage 2 is instructed to write - Optionally align the in-script scaffolding (
HALLUCINATION_PATTERNS,generate_keyword_headlines,generate_brand_headline) if you build automation on top of it — the shipped three-stage flow never invokes these helpers, so the reference files are what governs (contract §helpers)
Optional Enhancements
Set these env vars to enable additional context when generating copy:
COMPLIANCE_PATH— directory containing acompliance/ad_copy_validator.pymodule to add geographic validation (checks headlines reference the correct city/state)SERP_API_PATH— directory containingget_gmb_reviews.pyandanalyze_competitors_for_rsa.pyto add Google My Business social proof and competitor USP analysis to the context JSON
Both are optional. The script gracefully skips these features when the
modules aren't available. Interface details, the city/state gating that
couples the two hooks, and the fact that
rsa-single-account ships SERP modules this hook
can import: references/refresh-contract.md
§enrichment.
Safety
Read-only against Google Ads — the scripts run GAQL SELECT queries and
write only to the review sheet you own. Ad copy reaches Google Ads solely
through your Google Ads Editor import, after the review pass in rules.md.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

