Case studies

What I owned, what shipped and what changed. Company names stay private. The numbers stay exact.

A traffic engine and a revenue engine

Company
Enterprise B2B SaaS
Role
Led SEO and growth, in-house
Areas
SEO strategy, Site architecture, BOFU pages, Redirects

Most organic traffic was landing on pages that didn't sell. Rebuilding the site around two separate jobs took monthly organic traffic from 180K to 315K+ and made the USA the top region globally.

monthly organic traffic
180K → 315K+monthly organic traffic
blog traffic
10K → 28.7Kblog traffic
branded search
5K → 12K+branded search
USA became the top traffic region globally
#1USA became the top traffic region globally

Context

The company sells software to enterprise buyers worldwide. Organic search was growing. The real question was whether that growth reached the pages that sell.

The problem

Mapping the keyword universe against the site made the gap obvious. Almost all organic visits landed on informational pages. The product and solution pages, the ones that create pipeline, got almost none. Publishing more content would have widened the gap, not closed it.

What I owned

SEO strategy, site architecture, the redirect plan and the rollout. All of it, start to finish.

Approach

  • Split the site into two engines with separate jobs. Traffic pages earn category authority. Revenue pages turn that authority into demand.
  • Rebuilt the silo structure around that split and shipped the full redirect plan.
  • Built the bottom of the funnel. Comparison, alternatives, pricing, migration and competitor-capture pages aimed at buyers already evaluating.

Results

Monthly organic traffic grew from 180K to 315K+. Blog traffic grew from 10K to 28.7K. Branded search grew from 5K to 12K+. The USA became the #1 traffic-contributing region globally.

What I learned

Traffic pages and revenue pages are different products. Run them as one engine and the gap between them stays invisible.

From MQL counts to deal-level attribution

Company
Enterprise B2B SaaS
Role
Owner of the HubSpot stack and organic pipeline, in-house
Areas
HubSpot, Lead scoring, Attribution, Enrichment, SDR handoff

I took over the HubSpot stack so organic demand could be scored, enriched and traced to the deal. SEO-influenced pipeline grew 4x, from $2M to $8M.

SEO-influenced pipeline
$2M → $8MSEO-influenced pipeline
MQLs a month, on a PLG-led model
200 → 1,500MQLs a month, on a PLG-led model

Context

Traffic is the easy number to grow and the easy number to report. The harder question is what that traffic is worth. Answering it means connecting organic demand to the CRM, and the CRM to deals.

What I owned

The HubSpot stack. Workflows, forms, lifecycle stages, lead scoring and deal-level attribution. Plus the bottom-of-funnel pages that fed SDR conversations in the USA and the rest of the world.

Approach

  • Set up workflows, forms, lifecycle stages and lead scoring in HubSpot.
  • Added enrichment with Clay, Bitscale and Factors.ai. ICP fit became a property, not a guess.
  • Attributed pipeline at the deal level, not at the form fill.
  • Fed SDRs from comparison, alternatives, pricing, migration and competitor-capture pages.

Results

On a PLG-led model, MQLs grew from 200 to 1,500 a month. SEO-influenced pipeline grew 4x, from $2M to $8M.

What I learned

Sessions, MQLs and revenue live in different worlds. A blog post can move sessions without touching MQLs. A sharp BOFU page can move revenue while barely registering on the traffic chart. Watch the gap between the three, not any single line.

100+ placements inside the listicles AI engines already cite

Company
B2B SaaS brands
Role
Strategy, sourcing, negotiation and tracking
Areas
AEO, GEO, Listicles, Citation sources, Digital PR

AI answers for "best X" and "X alternatives" questions lean on a small set of third-party listicles. Instead of publishing more and hoping, I got brands placed inside the lists the engines already trust. 100+ placements and counting.

listicle placements acquired for clients
100+listicle placements acquired for clients
every target chosen because AI engines cite it today
Already citedevery target chosen because AI engines cite it today

Context

Ask ChatGPT, Perplexity, Gemini or an AI Overview for the best tools in a B2B category and the answer is usually assembled from a handful of third-party listicles and comparison pages. If a brand isn’t on those pages, it usually isn’t in the answer, however good its own site is.

The problem

Most brands respond to AI search by publishing more on their own domain. That helps search. It rarely moves the AI answer for category and comparison questions, because the engines cite sources they already trust on those queries.

What I owned

The whole loop. Prompt research, citation-source mapping, target selection, sourcing through publishers and placement partners, negotiation, client approval and live tracking.

Approach

  • Built the buyer prompt set for each category. Best-of, alternatives, comparison and use-case questions.
  • Mapped every prompt to the exact pages AI engines cite for it, across engines, and ranked those pages by how often they appear.
  • Kept only targets that AI engines were already citing for the client’s category.
  • Sourced placements through publishers and partners, and kept a claims-to-verify register so every description of a client was accurate before it went live.
  • Tracked every placement from approval to live.

Results

100+ listicle placements acquired for clients, each inside a page AI engines were already citing for the client’s category.

What I learned

On category questions, AI visibility is mostly an off-site problem. Own-site content earns rankings. Placement on the pages the engines already trust earns the mention.

An internal linking engine writers actually use

Company
Own build
Role
Designed, built and run across B2B SaaS programs
Period
2026
Areas
Claude Code, Screaming Frog MCP, Hugging Face, Ollama, Search Console API, SE Ranking

A pipeline that reads a site crawl, Search Console data and keyword demand, matches every paragraph to the page it should link to with semantic embeddings, drafts the sentence when one is needed, and hands writers a sheet sorted by impact.

Context

Internal linking is one of the highest-leverage fixes in SEO and one of the worst done by hand. Someone skims a few posts, links the obvious phrase, and moves on. The pages that need authority most, the ones ranking on page two, rarely get it.

What I built

A repeatable pipeline run from Claude Code on any site.

  • Inventory. Claude runs the crawl through Screaming Frog MCP, or reads a saved crawl export. It keeps indexable 200 pages and splits them into source pages that carry links and target pages that should receive them. Orphan and thin pages get flagged.
  • Demand. Pulls three months of Search Console data per page. Pages with strong impressions, positions around 5 to 20 and weak CTR get pushed up. The queries a target already ranks for become its anchor candidates, because they are proven demand.
  • Value. Batches every anchor candidate into one SE Ranking call for volume, difficulty and intent. Commercial and buyer intent ranks above generic phrases.
  • Matching. Embeds every source paragraph and every target (title, description and ranking queries) with BAAI/bge-base-en-v1.5 from Hugging Face, then keeps only pairs above a cosine similarity floor.
  • Placement. If the anchor already sits in the paragraph, the instruction is to link those words, no rewrite. If not, a local llama3.2:3b on Ollama drafts one short sentence that carries it.
  • Guardrails. At most two new links per source page. Caps per target. No self-links, no links that already exist on the live page, no generic or brand-only anchors.
  • QA. Every row is checked. One bracketed anchor, the right target title, no duplicates. The semantic fit distribution is reported so the team can see how strong the set is.

Output

One sheet, sorted by a 0 to 100 priority score. Each row tells the implementer the exact sentence to find, the words to link, the target, whether it is an exact or topical match, the similarity score, how often that anchor is already used site-wide, and why the link matters.

What I learned

Small details decide whether a pipeline like this gets used. qwen3 leaked its reasoning into drafts, so drafting moved to llama3.2:3b. The model matters less than the guardrails around it.

The full method is published as a free Claude skill, the Internal Linking Engine. Read it or download it.

Automating the repeatable SEO work

Company
Own build
Role
Designed, built and run across in-house and client programs
Period
2025 to present
Areas
Claude, MCP, Ollama, Hugging Face, n8n, HubSpot API

Agents and models on Claude, Ollama, Hugging Face and n8n that run clustering, audits, reporting and small page changes. The team spends its time on diagnosis instead.

Context

A lot of SEO and growth work repeats. Clustering, crawls, audits, reporting, small page changes. Done by hand, it takes the time a team needs for diagnosis and strategy.

What I built

  • An SEO NLP engine. BERT models from Hugging Face and local LLMs running on Ollama, wired into Claude over MCP. It handles keyword clustering, intent classification, content gaps, entity extraction and internal linking.
  • Agentic SEO operations. n8n and Claude agents that push SEO changes to staging without dev tickets and deploy landing pages straight to the domain.
  • An audit library. Claude skills for technical, AI visibility, schema, page speed, ranking-factor, brand-fact and entity audits. Screaming Frog crawls run through MCP and come out as audits a dev team can act on.
  • Reporting on live data. Weekly SEO reports, performance trackers and MBR decks built from the source, not assembled by hand.
  • Tools without an engineering queue. A calculator shipped with zero engineering, and a Next.js leads dashboard on the HubSpot API.

Results

SEO changes reach staging without a dev ticket. Landing pages deploy without an engineering queue. Reports and decks come from live data instead of manual assembly.

What I learned

The models are the easy part. The value sits in small, dull systems around them that run the same way every week and check their own numbers.