Install the Codex skill
The kit includes .agents/skills/codex-seo-weekly-review/SKILL.md and the seo-agent/ scripts it calls. For a fresh Grow AI Skills checkout, download the ZIP, inspect its paths, and extract it at the repository root:
cd /path/to/growaiskills
unzip -l /path/to/codex-seo-weekly-review-kit.zip
unzip -n /path/to/codex-seo-weekly-review-kit.zip -d .
test -f .agents/skills/codex-seo-weekly-review/SKILL.md
test -f seo-agent/gsc_fetch.py
unzip -n leaves existing files untouched; if this repository already contains older scripts, compare and update those files before running the new skill. Open this repository as the Codex working directory and ask $codex-seo-weekly-review Run this week's SEO review. Codex discovers project skills under .agents/skills and may also choose one automatically when the request matches its description. If the new skill does not appear, reopen Codex. Installing the skill only adds instructions and scripts; Search Console authorization is the separate step below.
This kit is wired to Grow AI Skills: the collector uses sc-domain:growaiskills.com, and the selector expects this site's content manifests and php bin/engagement.php event export. For another site, map the property, canonical domain, page catalog, and actual action events before treating the commands as runnable.
Decide what a useful outcome means
In the kit's BRIEF.md, name the page's intended next action and the event that records it. Grow AI Skills has events such as prompt_copy, resource_download, and next_step_click. A count may include repeat actions by one visitor and actions from social or direct traffic. It is a reason to inspect a page, not proof of a sale, signup, or Google-organic conversion. Leave business_conversion_definition empty in state.json until an actual outcome and its channel attribution are verified. Copy STATE.template.json and LOG.template.jsonl to state.json and log.jsonl before the first run; the runtime files stay out of Git.
Machina's sponsored SEO post advocates choosing pages with both search exposure and conversions. This implementation uses the same weekly review sequence but has a narrower selection rule because the available Grow AI Skills event export cannot attribute conversions to organic search. Do not turn a page's action count into a conversion claim.
Authorize Search Console once
The Search Console API uses OAuth 2.0. Use an account with read access to sc-domain:growaiskills.com, enable the Search Console API in its Google Cloud project, and create a Desktop OAuth client. For a local Codex task, Google's Application Default Credentials setup supports a client ID and an explicit scope for an API outside Google Cloud:
gcloud auth application-default login \
--client-id-file=/absolute/path/outside/repository/oauth-client.json \
--scopes=https://www.googleapis.com/auth/webmasters.readonly
Keep the client file and credential store outside the site repository. The collector calls gcloud auth application-default print-access-token on each run, so the task does not need a pasted token. A one-off GSC_ACCESS_TOKEN environment variable also works, but it expires. A 401 means the token or scope needs checking; a 403 calls for checking property access, API enablement, and possibly the quota project. The kit reports these failures instead of replacing missing data with its example fixture.
Collect two finalized Search Console windows
From the Grow AI Skills repository root, run:
mkdir -p seo-agent/data seo-agent/runs
python3 seo-agent/gsc_fetch.py windows
php bin/engagement.php 60 > seo-agent/data/engagement.json
python3 seo-agent/weekly.py \
--current seo-agent/data/gsc-current.json \
--previous seo-agent/data/gsc-previous.json \
--events seo-agent/data/engagement.json \
--output seo-agent/runs/latest.json
The collector asks the Search Analytics API for recent date rows with type: web and dataState: final. It then requests page rows for two adjacent 28-day periods ending on the latest returned finalized date. If that date is September 21, 2026, the current period is August 25–September 21 and the previous period is July 28–August 24. The script saves raw dated requests and responses alongside normalized JSON for the selector, plus a dated copy under seo-agent/data/history/ so the next run cannot overwrite the prior evidence. It counts and excludes other subdomains or URLs with query strings from the page queue while retaining them in the raw files. Inspect that excluded count before trusting the result.
Search Console returns top rows, not a guaranteed complete inventory, even when paginated. If a page has no row in the previous export, the report says previous: null, not zero. The selector also rejects a mismatched property, unfinalized export, duplicate canonical page, invalid metrics, or an engagement export that ends before the search window. A failure is a data problem to resolve, not a reason to invent a baseline.
Read the candidate as a review queue, not a verdict
For this site, the screening rule requires at least one search click and one recorded site action during the current window, then picks the eligible page with the most search clicks, breaking ties by action count. This is a local editorial rule, not a Google ranking rule. The included synthetic fixture selects a comparison page with 12 current clicks and 240 impressions, against 7 clicks and 180 impressions previously, plus three all-channel next_step_click events. Those three events cannot be assigned to the 12 Google visitors. With no qualifying page, the script returns NO_SUPPORTED_CANDIDATE and stops the audit.
Check the selected page's actual query and next step
When the report selects a page, run python3 seo-agent/gsc_fetch.py queries. The collector requests query rows for that exact page and the current window and writes seo-agent/data/gsc-selected-query-raw.json. A page-level export has no query strings; a missing query response cannot support a confident search-intent diagnosis. Google may withhold query rows, so no returned rows means unknown, not “nobody searched.”
Give Codex the report, raw query response, live page, BRIEF.md, state.json, and log.jsonl. Have it check the live response and canonical URL, then use URL Inspection for indexed status if available; an HTTP 200 alone does not prove indexing. Compare one returned query with the current search results and the page's opening answer. Check whether the page's visible next step matches the recorded action. For AI Overviews and AI Mode, Google's guidance calls for ordinary Search eligibility and useful visible content, with no special AI text file or schema.
The output should name one exact change and its observable before-and-after check, or NO_CHANGE. For example, a returned query about setup could justify replacing an opening that jumps straight to advanced options with the verified setup steps; the evidence would be the query row, the current page text, and the changed public text after approval. If the query is withheld, the page already answers it, or index status is unavailable, record that limit and avoid a forced rewrite. The runbook prompt forbids editing, deploying, or requesting indexing before review of the exact proposed change.
Schedule the review and inspect the first run
A Codex desktop scheduled task can run this local workflow each week while the computer and app are available. The kit includes a prompt that collects the dated inputs, runs the selector, audits one supported page, and appends a dated log entry. Its first unattended run is useful only after the read-only OAuth flow works on that machine. Check the saved date probe, both raw page responses, any excluded rows, the selected page or data-gap status, the filtered query response, and the written log. At the next review, compare equal finalized windows and the recorded baseline; do not attribute any movement to an edit without accounting for other changes. The local synthetic checks pass, but a live weekly run, organic conversion join, and ranking lift have not been verified.
