# Search visibility tracking

The website publishes two discovery indexes:

- `recruiter-searches.txt` contains named searches that include Aryan Putta.
- `recruiter-searches-generic.txt` contains role-first searches that omit the
  name, such as `AI infrastructure intern candidate` and `GPU systems intern`.

Google Search Console is the source of truth for whether the site actually
appears for a query. Page metadata cannot see Google impressions or the exact
search query that produced them.

## Measurement loop

1. Open the `aryanputta.com` property in Google Search Console.
2. Open Performance, set the date range, and export the Queries table.
3. Record query, page, impressions, clicks, CTR, position, and whether the
   query is `named` or `role_first` in `seo-search-performance.json`.
4. Add recurring role-first queries with impressions but low clicks to the
   relevant page copy, project descriptions, or `llms.txt` context.
5. Add queries with zero impressions only when they describe real work,
   education, or roles Aryan is actually pursuing.

Prioritize high-impression, low-CTR queries and role-first queries with an
average position between 4 and 20. Do not treat invented keyword combinations
as evidence of experience or employment.

The worker also stores page-level weighted CTR and position summaries,
role-first impression totals, and the top position 4 to 20 opportunities. These
measure homepage, projects, writing, and contact-page performance without
changing the visual design.

## Autonomous growth command

The repo includes `scripts/fetch_search_console.py` and
`scripts/grow_seo.py`. The scheduled GitHub Action fetches the last 28 days of
Search Console data, stores observed metrics, separates named from role-first
queries, detects high-performing patterns, replicates those patterns across
approved related roles, and appends observed gaps to the generic index.

The worker is autonomous after the two repository secrets are configured. It
runs daily, makes one Search Console API request per scheduled run, and caps
the response at 5,000 rows. Workflow concurrency prevents overlapping runs.
There is no model API, paid SEO API, or retry loop.

## Optional Kimi analyst

The workflow can also run `scripts/analyze_seo_with_kimi.py` on Mondays. Add a
`KIMI_API_KEY` repository secret only if you intentionally want this optional
analysis. The script sends at most 100 observed query rows, limits the response
to 1,200 output tokens, makes no web-search tool calls, removes identity-bearing
queries such as names, email addresses, and phone numbers, and never sends full
page URLs or the profile JSON. It writes only the report-only
`kimi-seo-analysis.md` file. It never edits the site or applies model-generated
keywords. Without the secret, it records a skipped report and the free
deterministic worker continues normally.

- `GSC_SERVICE_ACCOUNT_JSON`: a Google service-account JSON credential whose
  email has read access to the `aryanputta.com` Search Console property.
- `GSC_SITE_URL`: `https://aryanputta.com/`.

One-time setup: create a Google Cloud service account with the Search Console
API enabled, add its email as a delegated owner or full user on the verified
`aryanputta.com` property, then add the JSON credential as the GitHub repository
secret `GSC_SERVICE_ACCOUNT_JSON` and add `GSC_SITE_URL` with the exact property
URL. The daily workflow skips cleanly until these secrets exist.

It never fabricates employers, projects, degrees, or experience. It only learns
from observed Search Console queries and approved topics already represented by
the profile.

The ranking logic is documented in `SEO_SEARCH_RANKING.md`. It uses a bounded
retrieval, evidence-match, ranking, winner-transfer, and feedback loop. The
worker can improve phrase coverage automatically, but Google and recruiter
platform ranking remains an external system.
