An automated SEO team that runs on a timer: it finds topics Google already half-gives us, writes the missing content, asks you to approve it, publishes it, then keeps tuning the live pages and measures whether any of it made money.
The Factory can research, write, draft, preview and measure entirely on its own. The single thing it cannot do is put new content on uktherapyguide.com without a human approval. Approval is a normal GitHub pull request — you read the change, you click Merge, it publishes on the next run. Close it instead and the work is parked, never re-opened.
Weekly. Reads Google Search Console for queries we already rank 5th–25th for, prices them with keyword tools, and scrapes what the pages beating us actually cover. Writes a ranked backlog. Publishes nothing.
Daily, one topic at a time. Research → write → anti-slop gate → open a pull request for you → publish on merge. Two human gates sit in this lane.
Mondays and Thursdays. One small change to one live page, then it waits 2–4 weeks and keeps or reverts it on the real Search Console numbers.
Enhance — the usual one. We already have a page ranking for the topic; the Factory writes the sections it's missing and merges them into that live page. Cheap, fast, and it inherits the page's existing ranking. 15 of our 16 topics are enhancements.
Create — no page exists, so it builds a whole cluster: one main "pillar" page plus supporting posts, published through the uktg-screens toolkit. Slower, and a brand-new page takes months to be seen by Google. One cluster (deflecting-meaning) has gone this route.
seo-factory is the brain — it holds the plans, the research, the decisions, and every number on the dashboard. uktg-screens is the hands — it's the code that actually puts pages on the WordPress site. The brain never touches WordPress directly.Take reality testing — a topic that went live on 29 July. Here is its whole life, and every stage is a folder on disk you can open.
bin/promote-cluster — gate onestate/clusters/reality-testing/ — holding its plan, its research, its draft, its quality report and its optimisation history. That means the whole system is readable, diffable, and revertible with ordinary git. It also means there is no hidden state anywhere: if it isn't in a file, it didn't happen.Everything else runs unattended. These are the only two moments the Factory stops and waits for a person.
The strategy stage writes plans as planned. Running bin/promote-cluster <id> flips one to approved and lets research start. The command refuses plans with no analysed gap, no sections to add, or health-topic plans with no credentialed author.
Once the draft passes the quality gate, the Factory opens a pull request on the enhance/<topic> branch. The diff is the content — the rendered sections exactly as they'll appear. Merge it and the next morning's run publishes it to the live page.
Merging is the approval — there is no separate "publish" button. The dashboard shows open gates under Awaiting you and hands you the merge link. A gate PR left sitting gets a Slack nudge after three days.
Six scheduled jobs, all as systemd timers on this machine. The dashboard's Schedule panel shows their real next/last run, so a job that silently stopped is visible rather than assumed healthy.
| Job | When | What it does |
|---|---|---|
| Dashboard data | Daily 06:30 | Pulls the fresh money + Search Console snapshot the dashboard renders |
| Discovery | Sunday 06:00 | Refills the opportunity backlog |
| Enhance | Daily 08:00 | Publishes anything you merged, re-checks stuck drafts, opens gate PRs, then drafts the next topic |
| Optimise | Mon + Thu 07:30 | One tuning change on one live page, and resolves any change whose window has closed |
| Conversion monitor | 1st of the month | Flags a topic whose clicks rose but whose enquiries-per-click fell — wrong-intent traffic |
| Read-outs | Sunday 07:00 | Regenerates the deep-dive reports (site audit, conversions, CRO scorecard) |
The dashboard is read-only. It never approves, publishes or changes anything — it renders the files on disk, so what you see is literally the system's own state. It's one long page; the tabs across the top jump to each section.
Six columns, left to right, in the order work moves. Each card is one topic; click it to open that topic's own page — its plan, the drafted sections, the anti-slop verdict per section, and the merge button if it's waiting on you.
Cards can't lie about being busy. A topic stuck in Research with no file activity for 12 hours turns Needs attention instead of showing a hopeful progress bar, and a draft that the quality gate blocked reads "⚠ 2/6 sections blocked" rather than "authoring content".
Last 90 days, read from our own attribution tracker — not Google Analytics. A "new client" is someone's first ever tracked purchase, credited to the content page their journey started on.
Underneath sit two drill-downs. Benchmark month by month is the full history since organic tagging went live in March — click a month to see which landing pages produced it. Converting pages is the same data sliced the other way: every page that has ever produced a client, click one for its monthly split.
Then two panels that frame the whole strategy: Golden tier (pages that both convert and have search headroom — where effort pays twice) and The leak (posts pulling hundreds of clicks and converting nobody).
Every edit the Factory has made to the live site, with the page title linking straight to the live URL. updated = an enhancement published through the gate. optimised = the tuning loop's own change. reverted = a tuning change that lost and was rolled back.
This is the honest answer to "what has it actually done to my website" — it's built from the run logs, not from anyone's memory.
The four tiles are site-wide reality. Below them, By cluster puts each topic's clicks next to its forms, people and pounds — so a topic with traffic and no money is obvious at a glance.
SERP positions tracks every enhanced or live page: its average Google position over the last 14 days against the 14 before. ▲ means the page moved up the results. This is the fastest read on whether an enhancement worked, weeks before conversions could show it.
Open gate PRs, each with its Review-and-merge link, plus any plans sitting at the promote gate. When it says "No open gates — nothing waiting on you", the pipeline genuinely has nothing blocked on a human.
If the Slack webhook itself is broken, a red banner appears here — otherwise a dead webhook would silently swallow every alert the pipeline believed it sent.
Read straight from systemd, so an inactive timer shows (off) and a never-run job says "never" — no wishful thinking. Underneath, Which clusters the loop touches explains why the tuning loop only acts on 1 of 16 topics: a topic joins the loop when its status becomes live, which today only deflecting-meaning is.
A flip-through of every topic showing its plan: which live page it enhances, the exact list of sections being added, its target keyword, and whether it's flagged as a health topic requiring a clinician-credentialed author. Click the title to open the full topic page.
Left: weekly clicks across every page in the tuning loop, with a chip per change — kept, watching, or reverted. Right: which plays pay off, ranked by the enquiry-form lift they've produced across every use.
A play needs 5 resolved uses before it counts as proven. One that loses 60% of the time gets ⛔ and the optimiser stops proposing it until a human clears its record. Today all three changes are still in their evaluation window, so the ledger reads honestly empty rather than guessing.
The long-form reports the pipeline generates — site audit, conversion analysis, CRO scorecard, discovery run, content-gap analyses. Newest of each type, rendered in-browser. Anything gone stale carries a "36d old" badge so you don't quote a number from a report nobody has refreshed.
The last three runs, each step with its timestamp, plus the run's duration, error count and API cost. Every loop writes one of these files when it finishes, so "the optimiser ran but did nothing" is distinguishable from "the optimiser never ran".
Every figure on the dashboard traces to one of four systems, refreshed by the 06:30 job each morning.
Clicks, impressions, average position, and which queries a page surfaces for. The source for opportunity-spotting and for every keep/revert decision.
The UKTG plugin that records real journeys — form submissions, bookings, purchases. Conversions are credited to the content page the visitor was actually on, not the site they first landed on.
The page inventory — what exists, what's indexable. 363 pages today. Also how enhancements are written back and then re-read to verify they landed.
Search volumes and difficulty, competitor page scraping, and one deep-research pass per topic for citable sources. Roughly £2–3 per topic researched, a few dollars a week on keyword data.
A visitor arrives on a blog post from Google, browses to a service page, and fills the form there. Naïve tracking credits the service page and the blog post looks worthless. We record the page the visitor was on at each step, so the post that earned the visit keeps the credit. That's the whole reason "The leak" panel is meaningful — those four posts pull 550+ clicks a quarter and genuinely convert nobody, rather than merely being under-credited.
SEO can't be A/B tested — there's one Google result per URL, so the only honest measurement is before-versus-after on the same page. Everything about this loop is built around not fooling ourselves.
Pull the numbers → resolve any change whose window has closed → pick one page with nothing in flight → form a hypothesis about why it underperforms → pick the matching play → commit it and deploy. Then stop. A page with a change in flight is locked, so two edits can never overlap and muddy the reading.
| What the numbers say | What it does | Why |
|---|---|---|
| Page improved, topic healthy | Keep | It worked. |
| Page improved, topic dropped | Revert + flag a human | The page probably won by stealing its neighbours' rankings. |
| Page got worse | Revert | Roll back to the previous version. |
| No real change, topic healthy | Keep | Reverting noise risks undoing a real gain hidden inside it. |
| Three flat results in a row | Stop, flag a human | The plays aren't moving this page; more tweaking is waste. |
| Enquiry forms collapsed 60%+ | Revert regardless of clicks | More traffic that converts less is not a win. |
The window is 14 days, or 28 for a quiet page — a low-traffic page needs longer for a real effect to clear its own week-to-week noise. A move smaller than the page's historical swing counts as no change at all, not as a win.
This is health content on a site people trust with a hard moment in their lives. Six things stand between the model and the website.
Writing happens only after a research pass has gathered real sources, and every claim-shaped sentence must carry a citation that resolves to one of them. An invented citation — or a claim with none — blocks the section. It never reaches a pull request.
Phrases that tell a reader they have a condition are blocked outright; the copy has to say "you may be experiencing". On health topics, a section without crisis support signposting (Samaritans, 116 123) is blocked too.
A topic whose sections failed the gate shows on the board as "⚠ 2 of 6 sections blocked", not as healthy work in progress. Each cycle re-checks stored drafts, so a gate fix applies retroactively without rewriting anything.
Published sections are wrapped in topic-scoped markers, so a re-run replaces them and can never duplicate. After writing, it re-reads the live page and confirms the content is actually there — a silent failure fails loudly instead.
Hard rule in code: the Factory never touches the enquiry funnel, the placement form, or the therapist directory. Those are the revenue path and stay under human control. The call-to-action injector refuses those targets outright.
Every autonomous commit is signed by a bot author, so git log separates machine work from human work. A bad change is a normal git revert plus a redeploy — the git history is the rollback mechanism.
An enhancement changes rankings over weeks; a brand-new page can take a quarter to be taken seriously by Google. The one created-from-scratch cluster has had almost no traffic since going live — that's expected for a new page, not a fault in the machine.
Fifteen of sixteen topics are enhancements to existing pages, and those deliberately end at "enhanced" rather than entering the loop — the optimiser's plays assume it owns the whole page, which it doesn't on a page the wider site also edits. So the loop currently works on exactly one topic.
Clicks are visible within weeks; a new client can take months and needs the visitor to actually reach a form. Judge an enhancement first on SERP position, then on clicks, and only much later on pounds.
Money and performance render from a snapshot file, not a live query. The header carries its refresh date — if that date is old, the job didn't run, and the Schedule panel will show why.