Free Resources

The Claude skills, local SEO playbooks and GoHighLevel automations I run my own business on. Every one has a written walkthrough so you can set it up yourself.

36 walkthroughs · updated Sep 29, 2026

Get every walkthrough, free

Drop your name and email and the full library opens up: every walkthrough, every download. I'll also send you the link to my free AI tools library, and you'll hear about new stuff first.

No spam. Unsubscribe from any email in one click.

Begin Here 4

Install Claude Code and Get Through Your First 30 Minutes

The current install command for Mac and Windows, the plan you actually need, and what to do in the first half hour so Claude knows your business.

claude-codesetupbeginners Updated Sep 29, 2026
Official install docs ↗

A lot of Claude Code tutorials still start with installing Node and fighting npm permissions. You can skip all of that now. Anthropic ships a one-line installer, and it updates itself.

Claude Code is different from the chat window at claude.ai. It runs in your terminal, inside a folder on your computer, and it can read and write the files in that folder. That’s the whole reason to use it.

Step 1: Get the right plan

Claude Code needs a paid account: Pro, Max, Team or Enterprise (or API credits through the Claude Console). The free claude.ai plan does not include it. Pro is where I’d start.

Step 2: Install it

On a Mac, open Terminal (Cmd + Space, type Terminal) and paste:

curl -fsSL https://claude.ai/install.sh | bash

On Windows, open PowerShell and paste:

irm https://claude.ai/install.ps1 | iex

If you already use Homebrew, brew install --cask claude-code works too, but that version won’t update itself. The native installer does.

Close the terminal, open a new one, and check it:

claude --version
claude doctor

A version number means you’re installed. claude doctor tells you what’s off when something is, which beats guessing. On Windows, Git for Windows is optional, but installing it gives Claude a Bash shell to work with.

Step 3: Give it a folder

Make one folder where your business work lives, and always start Claude from inside it.

mkdir ~/Claude
cd ~/Claude
claude

The first run opens your browser to log in. Use the same account you pay for. If you ever need to switch accounts, type /login inside Claude.

Don’t launch Claude from your home folder. It works out of whatever folder you start it in, and you want that to be a folder you picked on purpose.

Your first 30 minutes

What you want to do is teach it who you are before you ask it for anything big. Paste this:

Interview me about my business, one question at a time: what I sell,
who buys it, my service area, my prices, and how I talk to customers.
When we're done, write it all to a CLAUDE.md file in this folder.

CLAUDE.md is a file Claude Code reads at the start of every session. Once it exists, you stop re-explaining your business every morning. From here, try one real task you’d normally do by hand, like the follow-up text for a quote you sent last week.

Three keys worth knowing on day one: /help lists commands, /clear starts a fresh conversation, and Shift+Tab switches permission modes.

I wrote a longer beginner version on my blog: How to install Claude on Mac and Windows. It uses the older npm method, so if the two disagree, use the commands on this page.

One honest warning

Claude Code asks before it edits files or runs commands. Read those prompts. Hitting yes to everything is how people end up with a folder they don’t recognize. And skip any tutorial that tells you to put sudo in front of an install command. Anthropic’s own docs say not to.

Run Your Business Out of One Folder: CLAUDE.md, Skills and a Router

How I set up one folder so Claude knows who I am, which rules to follow and which skill file to open for each job. Starter templates included.

claude-codeskillstemplatesworkflow Updated Sep 29, 2026

Every time you open a new chat and explain your business again, you pay a tax. Your prices, your service area, the words you never want to see in your copy. After a while you get lazy about it, and the output gets worse.

What I do instead: everything runs out of one folder. Claude Code starts there every time, and a few plain text files do the explaining for me.

How the folder is laid out

my-business/
├── CLAUDE.md                  # who I am, the rules, where things live
├── .claudeskills/
│   ├── orchestrator-SKILL.md  # the router
│   ├── brand-voice-SKILL.md   # how I write
│   ├── seo-content-SKILL.md   # one file per kind of job
│   └── gbp-posts-SKILL.md
└── Clients/
    └── acme-roofing/
        └── context.md

Step 1: The root CLAUDE.md

Claude Code reads CLAUDE.md automatically at the start of every session. Mine covers who I am and what the business sells, the rules I never want broken, and one instruction that matters more than the rest: read the router first.

Here’s a trimmed starter. Fill in the brackets.

# CLAUDE.md

## Who I am
- Name: [Your name]
- Business: [What you sell, in one sentence]
- Customers: [Who buys, and where]
- Voice: read `.claudeskills/brand-voice-SKILL.md` before writing any copy

## First step on any task
1. Read `.claudeskills/orchestrator-SKILL.md`. It says which skill to use.
2. Read that skill file and follow its process.
3. If no skill fits, ask me before guessing.

## Rules
- Never invent reviews, results or client names.
- Ask before deleting files or sending anything to a customer.
- Prices: [your real prices, or "ask me"]
- Phone: [number]   Website: [url]

## Where things live
- Skills: `.claudeskills/`
- Client work: `Clients/[client-name]/` (read its context.md first)
- API keys: `.env` and `.mcp.json`. Never print them or copy them into other files.

Step 2: One skill file per job

A skill file is a plain markdown file with the process for one kind of work, like how you write a Google Business Profile post or how you quote a roof. Write it the way you’d train a new hire. Put a line at the top that says when to use it.

Step 3: The orchestrator

This is the file that keeps the folder from turning into a junk drawer. It’s a routing table. A request comes in, Claude matches it to a row, and opens that one skill file.

---
name: orchestrator
description: Route every request to the right skill file.
---

# Orchestrator

## How it works
1. Match the request to a row below.
2. Read that skill file, then do the work its way.
3. If any copy is being written, read brand-voice-SKILL.md first.
4. If nothing matches, ask me one clarifying question.

## Routing table
| If I ask for... | Use |
|---|---|
| Social post, Facebook, Nextdoor | social-posts-SKILL.md |
| Blog post, article, "something that ranks" | seo-content-SKILL.md |
| Google Business Profile post or photos | gbp-posts-SKILL.md |
| Quote, estimate, proposal | proposal-SKILL.md |
| Research a competitor or a market | research-SKILL.md |

## Multi-step jobs
"Write a blog post and promote it":
1. seo-content-SKILL.md
2. social-posts-SKILL.md (turn the post into 3 social posts)

Why a router instead of one giant file

If you stuff every process into CLAUDE.md, Claude reads all of it on every task, including the parts that have nothing to do with what you asked. Anthropic’s own docs say to keep a CLAUDE.md under about 200 lines. The router keeps the root file short and pulls in the detail only when it’s needed.

Claude Code also has an official skills feature (.claude/skills/<name>/SKILL.md, callable with a slash command). It works fine. I keep my plain .claudeskills/ folder because it’s just markdown. I can copy a skill into a client’s folder or hand it to someone who doesn’t use Claude Code at all.

One honest warning

This setup rots if you don’t maintain it. When Claude gets the same thing wrong twice, fix the skill file, not the chat. Correcting it in the chat only lasts until you close the window. And trim the root CLAUDE.md every month or so, because these files only ever grow.

The MCP Servers I Run Every Day (and a Clean .mcp.json)

Firecrawl, Perplexity, Playwright, Notion and Gemini: what each one does for me, the exact packages, and a config file with placeholder keys.

claude-codemcpfirecrawlperplexityplaywright Updated Sep 29, 2026

Out of the box, Claude Code can only work with what’s in your folder and what it already knows. MCP servers give it hands: a way to search the live web, pull a competitor’s page, drive a browser or write to your Notion. Each one is a small program Claude Code starts in the background and talks to.

I run five of them nearly every day. Here’s what each one is actually for.

What each one does

  1. Firecrawl (firecrawl-mcp): turns a web page into clean text. I use it to pull a competitor’s service pages, or a client’s current site before a rebuild. Key from firecrawl.dev, starts with fc-.
  2. Perplexity (@perplexity-ai/mcp-server): live web research with sources. Market questions, who ranks for what in a given city, anything newer than Claude’s training. It runs on Perplexity’s API, which is billed separately from a Perplexity Pro subscription. Key from console.perplexity.ai.
  3. Playwright (@playwright/mcp): a real browser Claude can drive. Screenshots, clicking through a form to see if it actually submits, checking a page at phone width. No key.
  4. Notion (@notionhq/notion-mcp-server): reads and writes pages and databases. Create an internal integration at notion.so/profile/integrations, then give it access to the pages you want it to see. It can’t see anything you don’t share with it.
  5. Gemini (aliargun/mcp-server-gemini): a second model for second opinions. Before I commit to an approach, I ask Gemini to poke holes in it. Key from Google AI Studio.

Four of these have a longer walkthrough in the Tools section. Start with Firecrawl and Perplexity. Then read Playwright. Then Gemini. This page is the short version so you can get all five running at once.

The config file

Put this in a file named .mcp.json at the root of your folder and swap in your keys.

{
  "mcpServers": {
    "firecrawl": {
      "command": "npx",
      "args": ["-y", "firecrawl-mcp"],
      "env": { "FIRECRAWL_API_KEY": "fc-your-key-here" }
    },
    "perplexity": {
      "command": "npx",
      "args": ["-y", "@perplexity-ai/mcp-server"],
      "env": { "PERPLEXITY_API_KEY": "your-perplexity-key" }
    },
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    },
    "notion": {
      "command": "npx",
      "args": ["-y", "@notionhq/notion-mcp-server"],
      "env": { "NOTION_TOKEN": "ntn_your-token-here" }
    },
    "gemini": {
      "command": "npx",
      "args": ["-y", "github:aliargun/mcp-server-gemini"],
      "env": { "GEMINI_API_KEY": "your-gemini-key" }
    }
  }
}

These all run through npx, so you need Node.js installed for this part, even though Claude Code itself doesn’t need it. Restart Claude Code, approve the servers when it asks, then type /mcp to see which ones connected.

Or add them from the command line

If you’d rather not hand-edit JSON, claude mcp add writes the config for you. These two come straight from each project’s own README:

claude mcp add perplexity --env PERPLEXITY_API_KEY="your_key_here" -- npx -y @perplexity-ai/mcp-server
claude mcp add playwright npx @playwright/mcp@latest

By default that saves the server for the current folder only. Add --scope user to get it in every folder, or --scope project to write it into .mcp.json. Then run claude mcp list to check the connections.

For Notion, Notion itself now points people to its hosted server instead of the local package. You sign in from /mcp instead of pasting a token:

claude mcp add --transport http notion https://mcp.notion.com/mcp

The longer walkthrough, with the Chrome extension, is on my blog: adding MCP servers to Claude. It uses an older Perplexity package name, so go with the one on this page.

One honest warning

That file holds live API keys. If your folder is a git repo, add .mcp.json to .gitignore before your first commit. Claude Code can also pull keys from your environment (write "${FIRECRAWL_API_KEY}" as the value), which is the safer way if you share the folder. And every server loads its tools into every session, so turn off the ones you aren’t using from /mcp.

Make Claude Write Like You: a Voice File and a Banned Word Check

The voice file I keep in every project, the banned list that goes in it, and a short Python script that fails any draft with an AI tell or a dash.

claude-codecopywritingvoicepython Updated Sep 29, 2026

You can tell Claude “write in a casual, direct tone” all day. It’ll agree and hand you back something that sounds like every other AI post on Facebook. Tone adjectives don’t do much.

What works is a file with your actual rules and your actual writing in it, plus a script that fails the draft when it slips.

Step 1: Write the voice file

Save it as .claudeskills/brand-voice-SKILL.md, or anywhere you like, as long as your CLAUDE.md tells Claude to read it before writing copy.

# Brand Voice: [Your name / business]

## Who's talking
[One paragraph: what you do, how long you've done it, who you serve.]

## Tone rules
- Short sentences. Plain words you'd say out loud on a job site.
- Specific over vague: "$43", "took 55 days", never "significant savings".
- One honest downside per piece. Nobody trusts a post with zero cons.
- No em dashes. Use a period, a comma or parentheses.

## Phrases I actually use
- "[paste 3 to 5 things you say all the time]"

## HARD NO (never write these)
leverage, seamless, robust, elevate, unlock, delve, game-changer,
in conclusion, best practices, at the end of the day, secret sauce.
No "It's not about X, it's about Y". No "Less X. More Y."

## Gold standard samples
[Paste 3 real things you wrote that got a good response:
a Facebook post, an email, a text to a customer. Unedited.]

## Before you hand me a draft
1. Check every line against HARD NO.
2. Read it next to the samples. Same person?
3. If it sounds like a product page, rewrite it rougher.

The samples section is where most of the value is. The rules tell Claude what to avoid. The samples show it what you sound like on a normal day. Use real posts, typos and all.

Step 2: The checker

Rules in a file still get ignored sometimes, so I don’t trust a draft until a script has read it. Mine is a bigger version of this one, but this is the core and it’s enough to start:

#!/usr/bin/env python3
"""voicecheck.py: fail a draft that contains banned phrases or dashes."""
import re, sys

BANNED = [
    "leverage", "seamless", "robust", "elevate", "unlock", "delve",
    "game-changer", "game-changing", "in conclusion", "best practices",
    "at the end of the day", "secret sauce", "let's dive in",
]
DASHES = "\u2014\u2013"  # em dash, en dash

text = open(sys.argv[1], encoding="utf-8").read() if len(sys.argv) > 1 else sys.stdin.read()
problems = []
for n, line in enumerate(text.splitlines(), 1):
    low = line.lower()
    for phrase in BANNED:
        if re.search(r"(?<![\w-])" + re.escape(phrase) + r"(?![\w-])", low):
            problems.append(f"line {n}: banned phrase '{phrase}'")
    if any(d in line for d in DASHES):
        problems.append(f"line {n}: dash (use a period or a comma)")

for p in problems:
    print(p)
print("FAIL" if problems else "PASS", f"({len(problems)} found)")
sys.exit(1 if problems else 0)

Save it as voicecheck.py and run it on any draft:

python3 voicecheck.py draft.txt

It matches whole words, so unlock gets flagged but unlocked in a sentence about an actual door does not. Exit code 1 means it failed, which matters for the next step.

Step 3: Make Claude run it

Add this to the voice file or your CLAUDE.md:

Before showing me any copy, save it to draft.txt and run
python3 voicecheck.py draft.txt. If it fails, fix the lines it
lists and run it again. Only show me the draft after it passes.

Now the check happens before you ever see the draft. Every time you catch a new phrase you hate, add it to BANNED and to the HARD NO list. The two lists grow together.

One honest warning

The script only knows the words you gave it. A draft can pass with zero problems and still sound like nobody in particular. The samples do that part of the job, and the final test is reading it out loud. If you wouldn’t say it on a phone call with a customer, rewrite it.

My Claude Skills 10

Contractor Skills Pack for Claude: Maps, Reviews, Quotes, Slow Season

Seven free Claude skills for contractors: a business profile, market recon, Google profile scoring, site audit, review requests, estimates and a slow season plan.

contractorsskillsgbpreviews Updated Sep 29, 2026
Download the pack ↓

Most contractors I talk to have the same gaps. The Google Business Profile is half filled out, nobody asks for reviews on a schedule, and estimates go out as a text with a number in it. None of that is hard to fix. It just never gets done because you’re on a job all day.

This pack is the set of Claude skills I wrote for that. One setup skill learns your business, and six more you run whenever you need them.

What’s inside

  • Business Profile: 8 questions about your trade, city, services, reviews and customers. Run it once. Every other skill reads from it.
  • Market Recon: the top 5 competitors in your map pack, their review counts and weak spots, about 30 search terms grouped into themes, and a 30 day plan.
  • GBP Optimizer: scores your Google, Bing and Apple Maps listings across 11 factors and gives you the fixes in order.
  • Site Auditor: turns the results of a free audit (or 6 quick questions if you skip it) into a ranked fix list, plus a straight answer on fix vs. rebuild.
  • Review Engine: a personal 3 touch review request after each job, and replies for good and bad reviews.
  • Quote Builder: a written estimate with scope, exclusions, payment terms and Day 5 and Day 10 follow-ups.
  • Job Stacker: a plan to fill a slow month using win-backs, referrals, neighbors, property managers, a seasonal offer and local posts.

Install it

Claude.ai:

  1. Unzip the download. On a Mac the skills sit in a hidden folder called .claudeskills. Press Cmd + Shift + . in Finder to see it.
  2. Create a new Project and upload the 7 files from .claudeskills/ plus CLAUDE.md to the project’s files.

Claude Code: unzip, open a terminal in that folder and run claude. CLAUDE.md loads by itself and tells Claude which skill file to open for each request (Claude Code setup here).

Market Recon works with no extras. If you want live review counts pulled from Google Maps, the pack includes a small script. Put a Google Places API key in a .env file in the same folder (GOOGLE_API_KEY=your_key) and run:

python3 maps-recon.py "roofing contractor" "Plano TX"

First prompt

Set up my business profile.

Answer the 8 questions and Claude hands you a profile block. Make sure you save it: in a Claude.ai Project, paste it into the project instructions. In Claude Code, paste it at the bottom of CLAUDE.md. From here, every skill knows your trade and your city without being told again.

Then run the one that pays off first:

Score my Google Business Profile. I'm a roofing contractor in Plano TX.
Here's my listing: [paste your Google Maps link]

What comes back is a scorecard with each factor out of 5, the fixes in priority order, and a business description you can paste straight into your profile. For the website side, run the free audit, paste the results in, and Site Auditor turns them into a to-do list.

One honest limitation

The Quote Builder’s price table only covers DFW and Nashville, with a note to go 5 to 10% lower in smaller markets. If you work anywhere else, put your real supplier costs and labor rate in the prompt, or it will anchor on Texas and Tennessee numbers. And Claude can’t log into your Google profile for you. It writes every fix, and you still have to make them.

Local SEO Skills Pack: Audit Any Site, Then Build Its Schema

Two Claude skills. One scores a local business website out of 120 with a ranked fix list. The other writes the full schema markup package.

seoschemaauditskills Updated Sep 29, 2026
Download the skills ↓

A contractor’s website usually looks fine to the owner and says almost nothing to Google. The title tag is the company name, there’s no schema, and the city shows up once in the footer. Nobody catches it because nobody checks.

These are the two skills I use for the checking and the fixing.

What’s inside

  • Local SEO Auditor: scrapes the homepage and up to 3 service pages, then scores the site out of 120 across 6 categories. The first one is a match test: do the title, meta description and page copy all say the same thing about who you are, what you do and where. After that come schema, page basics, local signals, content and technical. The report is written in plain English and ends with a ranked fix list. It also has a pass/fail Build Gate you can run on a new site before launch.
  • Schema Generator: builds a 9 tier JSON-LD package and gives you 3 files: homepage schema, service page schema, and a list of placeholders it couldn’t confirm. Deployment steps are included for GoHighLevel, WordPress, Webflow, Wix and Squarespace.

Install in Claude Code

The auditor needs to read live pages, so it runs in Claude Code with Firecrawl (my Firecrawl setup).

  1. Unzip. Copy both folders, local-seo-auditor and local-seo-schema-generator, into .claude/skills/ inside your project. Use ~/.claude/skills/ instead if you want them in every project.
  2. Add Firecrawl if you haven’t yet:
claude mcp add --env FIRECRAWL_API_KEY=fc-YOUR_API_KEY --transport stdio firecrawl -- npx -y firecrawl-mcp
  1. Start claude in that folder. Claude Code finds the skills by itself, or you can type /local-seo-auditor.

If you only want the schema, create a Project in Claude.ai and upload local-seo-schema-generator/SKILL.md to its files. That one works without scraping as long as you give it your business details.

First prompt

Audit my website: https://yoursite.com
I'm a plumber in Frisco TX.

You get a score per category, what each failing item means in one or two sentences, and the fixes ranked by impact. Then hand the fixes to the second skill:

Create the full schema package for this business.
Business name, address and phone exactly as on my Google profile: [paste]
Services: [list each with one line]. Cities served: [list].
Deliver all 3 files.

Front-load the data. Every fact you leave out turns into a placeholder you fill in later. When it’s live, check it with Google’s Rich Results Test (how I do that).

One honest warning

Schema only helps when it agrees with everything else Google already knows about you. If the name, phone or address in it is off from your Google Business Profile by even a suite number, you’ve added a conflict instead of a signal. The generator can’t see your profile, so copy those three lines from the profile itself, not from memory.

GBP Optimization Skill: Google, Bing and Apple Maps in One Pass

A Claude skill that audits a Google Business Profile, writes the description, posts and products, then sets up Bing Places and Apple Business Connect.

gbplocal seoskills Updated Sep 29, 2026
Download the skill ↓

The Google Business Profile is where a lot of local calls start, and it’s the thing owners touch least. The hours are wrong, there’s one category, the description is a single sentence and the last post is two years old.

This skill is the checklist I run on a profile, written so Claude works through it in the same order every time. If you’d rather do it by hand first, this walkthrough covers the manual version.

What it covers

The skill runs 12 steps, numbered 0 through 11. In plain terms:

  1. Inputs first. Founding year, confirmed hours, your real service list (scraped from your site if Firecrawl is connected), service areas and your review link. If the hours aren’t confirmed, it stops right there.
  2. Audit and categories. It checks every field, then picks a primary category and extra ones based on what the top 3 competitors in your area use.
  3. Content. A description under 750 characters, your first Google Post, photo captions and 10 or more product entries.
  4. Ask Maps and AI answers. It tests the questions people ask about your business and flags what to fix on the profile itself.
  5. Reviews. A request script plus reply templates.
  6. Bing Places and Apple Business Connect. Import from Google, the fields to check after, and your first Bing post and Apple Showcase written for you.

Install

Claude Code: unzip and copy the gbp-optimization folder into .claude/skills/ in your project, or ~/.claude/skills/ to have it everywhere. Then type /gbp-optimization, or just ask about your Google profile and Claude picks it up.

Claude.ai: create a Project and upload gbp-optimization/SKILL.md to the project’s files.

Firecrawl is optional (my setup). Without it, paste your service list in yourself.

First prompt

Run the GBP optimization skill for Summit Roofing, roofing contractor in
Plano TX, founded 2016. Hours: Mon to Fri 7am to 6pm, Sat 8am to noon.
Website: https://yoursite.com
Service areas: Plano, Frisco, Allen, McKinney.

Putting the hours and founding year in the first message saves you a round of questions.

What comes back is a priority list in this order: hours, service areas, description, first post, products, categories, photos, Bing, Apple. Each one comes with the copy already written, so you can paste as you go.

One honest limitation

Claude writes everything, but it can’t sign in to your Google account, so the edits are still yours to make. If you have Claude drive the browser for you, heads up: some profile edit forms ignore typed text. The skill includes a small JavaScript workaround for exactly that. By hand, it’s copy and paste, and that part goes fast.

AEO Visibility Skill: Test Whether AI Names You, Then Fix the Gaps

A Claude skill that runs real buyer questions through AI answer engines, scores your site for how easily AI can quote it, and builds a 30 day fix plan.

aeoai searchchatgptskills Updated Sep 29, 2026
Download the skill ↓

People ask ChatGPT and Perplexity who to hire now. Most owners have no idea whether their name comes up, and the ones who do check type one question, see nothing and give up.

This skill turns that into a real measurement you can repeat every month. If you want to try it by hand first, here are the prompts I use.

What it does

Mode A, the baseline. Claude writes 8 to 12 questions a real customer would type, like “best roofer in Plano”, “is Summit Roofing legit” and “alternatives to [competitor]”. It runs each one and records four things: were you named, where in the answer, how you were described, and which source got cited. Your headline number is simple: named in X of Y questions.

Then it scrapes your homepage and top 2 service pages and scores them out of 100 on how easy they are for an AI to quote. That means a direct answer near the top of each page, your name, service and city stated plainly, a real about page, FAQs and tables, and AI crawlers allowed in robots.txt. Every question you missed gets one label: content gap, structure gap or authority gap. The label decides the fix.

Mode B, the 30 day sprint. Week 1 locks the question list and sets up tracking. Week 2 finds the gaps. Week 3 fixes 2 or 3 pages. Week 4 reruns the exact same questions and reports what changed.

Install

Claude Code: unzip and copy the aeo-visibility folder into .claude/skills/. Connect Perplexity (my setup) so Claude can run the questions itself, and Firecrawl (my setup) for the site score. Ahrefs, Search Console and GA4 are optional.

Claude.ai: upload aeo-visibility/SKILL.md to a Project. You’ll run the questions in ChatGPT yourself and paste the answers back in.

First prompt

Run an AEO baseline for Summit Roofing, https://yoursite.com, Plano TX.
Build 10 buyer prompts, test them, record named / described / cited for
each, score the site's AEO structure, and give me the AI Visibility Report.
Real output only. No invented numbers.

What comes back is a short report: “You show up in X of Y questions,” a quote of what AI actually said about you, the reasons it skips you, and the fixes in three groups (quick, medium, ongoing). It ends with what “fixed” looks like when you rerun the same questions in 30 days.

One honest limitation

AI answers change from day to day and from one engine to the next. One run is a snapshot, so don’t panic over a single bad result or celebrate a single good one. That’s why the skill locks the question list and reruns it every 30 days: the trend is what you watch. It also won’t promise that any AI will name you, and neither should anyone selling you AEO.

Knowledge Panel Skill: Your About Page, Wikidata and Crunchbase

A Claude skill that builds the three linked profiles Google checks before it shows a Knowledge Panel for a person, and links them to each other.

knowledge panelwikidataschemaskills Updated Sep 29, 2026
Download the skill ↓

When someone Googles your name before a meeting, a Knowledge Panel on the right side tells them you’re a real, specific person. Google only shows one when it can confirm the same facts about you from several independent sources. Most founders have those sources spread around, and none of them point at each other.

I ran this on my own name. The About page on this site is my entity home, and this skill is the process written down so Claude can repeat it.

What it builds

  1. An entity home page on your own site, usually /about/, with a Person JSON-LD block: name, title, companies, location and a sameAs list of every profile you have.
  2. A Wikidata item with the core statements (human, occupation, citizenship, official website), your profile IDs, and a reference on every single statement.
  3. A Crunchbase person profile that points back at the entity home.
  4. The loop, closed. All three link to each other, then you request indexing in Search Console.

It starts with Step 0, which is only questions: your exact title, your exact role at each company, your city, every profile URL. It won’t guess any of it. A wrong job title in public schema does more harm than a missing one.

Install

Claude Code: unzip and copy the knowledge-panel-entity folder into .claude/skills/. For the Wikidata and Crunchbase steps, Claude drives your browser through Claude in Chrome. You log in yourself. Claude never handles your passwords.

Claude.ai: upload knowledge-panel-entity/SKILL.md to a Project. Claude gives you the exact values for each field and you click through the forms.

First prompt

I want a Google Knowledge Panel for my name. Run the knowledge panel
skill. Start with Step 0 and ask me for the facts one at a time.

The output is the finished Person schema block for your About page, the list of Wikidata statements and references to add, and the Crunchbase fields filled in, with a checklist to confirm all three point at each other.

The step people skip

Step 4. Each profile gets built once, and nobody goes back to add the Wikidata and Crunchbase links to the About page schema. Make sure you redeploy after adding them, then check that it’s live:

curl -s https://yoursite.com/about/ | grep sameAs

Trust that, not the deploy log.

One honest warning

None of this guarantees a panel. Google decides. And Wikidata deletes items that don’t meet its notability policy, especially ones where the only reference is your own website. Get a podcast, interview or press mention as soon as you can, and add it as a reference on your Wikidata statements.

Wholesaler Skills for Claude Code: From Address to Offer

Six free Claude Code skills for wholesalers. Give it an address and get owner info, comps, a rehab budget, creative finance math and a ranked pipeline.

wholesalingrealestateskillsgithub Updated Sep 29, 2026
Get it on GitHub ↗

Researching one property by hand eats 20 to 45 minutes: the county assessor, tax records, Redfin, comps, then the math. Do that across a list and you never get to the phone. I built these so Claude does the digging and you do the talking.

It’s a folder of skill files plus a router (start-here-SKILL.md) that picks the right one from whatever you type.

What’s inside

  • Property Recon: owner, tax status, mortgage signals, red flags and a motivation score out of 25, from public records.
  • Comp Analyzer: recent sales, adjustments, an ARV with a confidence level, and your max offer.
  • Rehab Estimator: a line-item repair budget from listing photos or your own walkthrough photos, in three scenarios.
  • Seller Conversation Coach: paste a text thread, get the next message to send and why it works.
  • Creative Finance Structurer: subject-to, seller finance, lease option and wrap math next to a cash offer.
  • Deal Stacker: ranks your pipeline and tells you which 3 deals to work this week.

Install

You need Claude Code first (setup here). Then:

git clone https://github.com/miron-tech/wholesaler-claude-skills.git
cd wholesaler-claude-skills
claude

Working inside the cloned folder is the simplest way. The README also shows how to copy .claudeskills/ and CLAUDE.md into a folder of your own. Add Perplexity and Firecrawl (how I set those up) and it pulls live data instead of asking you for it. The Claude in Chrome extension is optional. It lets Claude fill out county assessor search forms for you.

First prompt

Run property recon on 4821 Cedar Ln, Memphis TN 38118.
Looks vacant, overgrown yard, mail piling up.

Then keep going in the same session: “run comps on it”, then “what’s my max offer with $50K in repairs”. Each skill reads what the last one found.

One honest limitation

County records are a mess. Some counties put everything online, some make you call. When a site won’t cooperate, Claude gives you the URL and tells you what to look up by hand. And the rehab cost tables are calibrated for DFW with adjustment factors for other metros, so check the numbers against a real contractor before you lock in an offer.

Realtor Skills for Claude Code: Leads, Comps, Listings and Sphere

Twelve free Claude Code skills for agents. Research a lead in about a minute, pull comps with a seller net sheet, and turn one address into 25+ listing assets.

realtorsrealestateskillsgithub Updated Sep 29, 2026
Get it on GitHub ↗

A new lead comes in while you’re at a showing. You want to reply fast, and you want the reply to sound like you already know the house. These skills do that homework, then keep going through the listing and the years after closing.

What’s inside

  • Lead Recon: property details, area context, a lead score and a reply ready to send. Fast mode takes about a minute.
  • Comp Crusher: 5 or 6 adjusted comps, three pricing tiers and a seller net sheet.
  • Listing Presentation: comps, marketing plan and net proceeds for the appointment.
  • Listing Arsenal: one address into 25+ assets, like MLS copy, social posts and emails.
  • Open House Machine: promo before, scripts during, follow-up after.
  • Nurture Coach: a 7 touch follow-up plan with the actual scripts.
  • Prospector: expired, FSBO and circle prospecting research plus scripts.
  • Market Intel and Neighborhood Dominator: weekly market content and a longer plan to own a ZIP code.
  • Sphere Engine and Review Engine: a 12 month past client calendar, review requests and referral asks.
  • Investment Analyzer: cash flow, cap rate and BRRRR math for investor clients.

Install

Get Claude Code running first (setup here), then:

git clone https://github.com/miron-tech/realtor-claude-skills.git
cd realtor-claude-skills
claude

Every skill works with details you type in. Add Perplexity and Firecrawl (my setup) and it pulls live data on its own. Results save to a local clients/ folder, and market data gets cached by ZIP, so the second lead in the same neighborhood goes faster.

First prompt

New Zillow lead: 4821 Cedar Ln, Dallas TX 75214. Run lead recon
and write me a text I can send in the next five minutes.

One honest limitation

Comps pulled from Redfin and web search are not MLS data. They’re good for getting ready fast. Check them against your MLS before a number goes in front of a seller.

HVAC Skills for Claude Code: Lead Recon, Quotes and Follow-Up

Five free Claude Code skills for HVAC contractors. A fast lead response, Good/Better/Best quotes, follow-up coaching, pipeline ranking and review requests.

hvaccontractorsskillsgithub Updated Sep 29, 2026
Get it on GitHub ↗

A lot of HVAC jobs are lost after the estimate goes out. One price goes to the homeowner, they collect two more quotes, and nobody calls back. These skills cover the parts that usually fall through: the first reply, the quote, and the follow-up.

What’s inside

  • Lead Recon: give it an address, get an estimated system age, tonnage, a lead class (Emergency, Hot, Warm, Cold) and a reply ready to send.
  • Quote Builder: Good / Better / Best options with financing math and a 15 year cost comparison.
  • Sales Coach: reads your thread with the homeowner, works out what kind of buyer they are, and writes the next message.
  • Job Stacker: ranks every open estimate and tells you which 3 to chase this week.
  • Review Engine: review requests timed by job type, follow-ups, and replies for good and bad reviews.

Install

Get Claude Code running first (setup here), then:

git clone https://github.com/miron-tech/hvac-claude-skills.git
cd hvac-claude-skills
claude

Or copy .claudeskills/ and CLAUDE.md into your own folder. Perplexity and Firecrawl (my setup) let it pull property details and local rebate programs by itself. Without them it asks you for the numbers. The README’s CRM section is for a private setup, and you don’t need it.

First prompt

Run lead recon on 3847 Oakwood Dr, Memphis TN 38128.
AC not cooling, called from Google LSA.

Then: “Build an estimate. 1,850 sqft, system is about 16 years old, customer is getting other quotes.”

One honest limitation

The Quote Builder won’t hand you a federal tax credit number to quote, on purpose. The federal 25C credit for heat pumps ended for anything installed after December 31, 2025 (IRS), and rebates change by state and utility. So it points the customer to their utility and to DSIRE instead. That’s one more step for them, but you never put a credit on a quote that turns out to be gone.

House Cleaning Skills for Claude Code: From Quote to Review

Five free Claude Code skills for house cleaners. Fast lead replies, recurring quotes in three tiers, sales coaching, pipeline ranking and review requests.

cleaninghomeservicesskillsgithub Updated Sep 29, 2026
Get it on GitHub ↗

Cleaning leads shop around. Whoever answers first with a real price has the edge, and after that most quotes die quietly because nobody follows up past “let me talk to my husband.” These skills handle the reply, the quote, and the follow-up, and they push one-time cleans toward recurring service.

What’s inside

  • Lead Recon: estimates home size, bed and bath count and cleaning time from the address, then writes a reply. Fast mode makes no API calls at all.
  • Quote Builder: Standard, Deep and Premium tiers at weekly, biweekly and monthly prices, with a higher first clean price and an add-on menu.
  • Sales Coach: reads the conversation, sorts the customer (quote shopper, DIY holdout, worried about trust) and writes the next message.
  • Job Stacker: ranks your open quotes and puts recurring leads ahead of one-time jobs.
  • Review Engine: review requests timed by the type of clean, plus a Nextdoor recommendation ask and a referral ask.

Install

Get Claude Code running first (setup here), then:

git clone https://github.com/miron-tech/residential-cleaner-claude-skills.git
cd residential-cleaner-claude-skills
claude

Or copy .claudeskills/ and CLAUDE.md into your own folder. Perplexity and Firecrawl (my setup) let it look up the house and local rates on its own. The README’s CRM section is for a private setup, and you can ignore it.

First prompt

Run lead recon on 2814 Autumn Ave, Memphis TN 38112. She wants
biweekly cleaning, found us on Google, has 2 dogs and a cat.

Then: “Build her a quote. She’s getting two other quotes.”

One honest limitation

The home size comes from public listing data. Claude can’t see the dog hair, the clutter or the state of the oven. Treat every quote as a starting range and confirm it with a few photos or a quick walkthrough before the first clean, or you’ll eat the difference on the job.

Restaurant Skills for Claude Code: Menu, Reviews and Catering

Six free Claude Code skills for restaurant owners. Market research, menu profit analysis, reviews, local marketing, catering packages and guest retention.

restaurantsmarketingskillsgithub Updated Sep 29, 2026
Get it on GitHub ↗

Restaurant owners don’t have a spare afternoon to rewrite the menu or plan a catering push. These skills take the desk work that keeps getting pushed to next week and turn it into a prompt you can run between lunch and dinner.

A router file (start-here-SKILL.md) reads what you ask for and picks the right skill.

What’s inside

  • Market Recon: nearby competitors with pricing and ratings, local demographics, and gaps you could fill.
  • Menu Engineer: sorts every item into Star, Plowhorse, Puzzle or Dog from your food costs, flags what’s losing money and rewrites descriptions.
  • Review Engine: review requests for Google, Yelp and TripAdvisor, reply templates, plus a framework for handling the bad ones.
  • Local Buzz: a weekly social calendar, Google Business Profile posts and seasonal promos.
  • Catering Builder: three-tier packages with per-person pricing, plus corporate outreach emails.
  • Guest Retention: birthday texts, win-back campaigns at 30, 60 and 90 days, and a VIP program.

Install

Get Claude Code running first (setup here), then:

git clone https://github.com/miron-tech/restaurant-claude-skills.git
cd restaurant-claude-skills
claude

Perplexity and Firecrawl (my setup) power the competitor and market research. The Claude in Chrome extension helps with Google Business Profile and Yelp pages. There’s a CRM connector mentioned in the README that was built for a private setup. Skip it.

First prompt

Run market recon for my Italian restaurant in Austin TX 78704.

Then paste your menu with plate costs and ask it to engineer the menu.

One honest limitation

This is the newest of my skill packs and the least tested in a real kitchen, so treat the output as a first draft. Menu Engineer is only as good as your food cost numbers. If you guess the plate costs, you get confident answers built on guesses. And foot traffic and demographic numbers come from web search, so read them as estimates.

Local SEO Playbooks 8

Fix Your Google Business Profile in One Afternoon

The order I work a Google Business Profile in, from category and services to hours, photos and weekly posts. One sitting, no paid tools.

gbpmapscontractors Updated Sep 29, 2026
Open Google Business Profile ↗

Most owners set up their Google Business Profile the week they opened and never touched it again. For a lot of homeowners that profile is the first thing they see, before your website, and Google is plain about how it picks who shows up: relevance, distance and prominence. You can’t move your shop. You can make the profile as relevant and complete as it gets.

When RankGrid pulled the profiles of 13,579 DFW contractors, the average rating was 4.72. Stars barely separate anyone. The work below does.

Step 1: Get the primary category right

The primary category is the setting that matters most. In Whitespark’s yearly survey of local SEO practitioners it keeps landing at the top of the list. Pick the most specific one that fits your main job. “Roofing contractor” beats “Contractor.”

  1. Search your main service plus your city in Google Maps.
  2. Open the top three results and read the category under each name.
  3. If they use a more specific category than you, that’s your first fix.

Add extra categories only for real service lines. Google’s own guidance says not to pick a category for every product or service.

Step 2: Fill in services under each category

Go to Edit profile → Services. Services sit under each category, so click into each one and add everything you actually do. Write one or two plain sentences per service: “Roof repair after hail and wind damage in Plano and Allen” beats a keyword list.

Make sure you keep those descriptions in a doc. I’ve seen them disappear after a category change.

Step 3: Service areas and hours

If you drive to customers, list the towns you actually work. Google allows up to 20. Distance still filters results, so a town 40 minutes away won’t show you just because it’s on the list.

Then check hours, including holidays. Wrong hours cost you calls from people searching “open now.”

Step 4: The description

You get 750 characters and no links. Say what you do, where, and for how long:

[Business] has served [region] since [year]. We handle [service 1],
[service 2] and [service 3] for homeowners in [city 1], [city 2]
and nearby towns. [One true line on what's different: owner on
every job, written estimates, licensed plumber on staff.]

Step 5: Photos

Real job photos, not stock: before and after, the truck, the crew, you. Then add one or two a month so the profile never looks abandoned.

Step 6: Posts on a pace

A post is a short update: the job you just finished, the town, one next step. Weekly is a good pace, every two weeks at minimum. Keep the phone number out of the post text (Google rejects a lot of posts for it) and use the Call now button instead.

Products are the last thing I touch. For many service businesses they sit pending, so add a few and move on.

Then test what Google’s AI says about you

Google retired the old Q&A section in late 2025. Now people can ask about your business in Maps and get an AI answer built from your profile, website and reviews. Ask it “What areas do you serve?” and “Do you do free estimates?” If an answer is wrong, fix the source, usually the description or services.

One honest warning

Don’t put keywords in your business name. “Smith Roofing | Best Roofer Plano” breaks Google’s guidelines, and a competitor can report it and get your profile suspended. Use the name on your truck and your invoices.

Local Business Schema You Can Copy, Paste and Test

A working schema block for a local service business (type, service, areaServed, sameAs), how to test it in Google's tools, and a Claude prompt that writes yours.

schemajsonldcontractors Updated Sep 29, 2026
Open the Rich Results Test ↗

Schema is a block of code that tells Google, in its own format, exactly what your business is and where it works. Without it Google reads your page text and guesses. When RankGrid live checked 10,828 DFW contractor websites, 55% had no local business schema on the homepage. It takes about twenty minutes to add.

It won’t rank you by itself. What it does is remove the guessing about who you are, what you do and where.

Step 1: Pick the most specific type

Google’s docs say to use the most specific LocalBusiness subtype you can. Schema.org has Plumber, Electrician, RoofingContractor, HVACBusiness, GeneralContractor and HousePainter, among others. If nothing fits, plain LocalBusiness is fine.

Step 2: Paste this into your homepage

Here’s a full example for a made up business. Swap every value for yours.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Plumber",
  "@id": "https://www.example.com/#business",
  "name": "Sample Street Plumbing",
  "url": "https://www.example.com/",
  "telephone": "+1-972-555-0142",
  "image": "https://www.example.com/images/truck.webp",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "100 Sample St",
    "addressLocality": "Frisco",
    "addressRegion": "TX",
    "postalCode": "75034",
    "addressCountry": "US"
  },
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
    "opens": "07:00",
    "closes": "18:00"
  }],
  "areaServed": [
    { "@type": "City", "name": "Frisco, TX" },
    { "@type": "City", "name": "Plano, TX" },
    { "@type": "City", "name": "McKinney, TX" }
  ],
  "sameAs": [
    "https://www.facebook.com/samplestreetplumbing",
    "https://www.yelp.com/biz/sample-street-plumbing-frisco"
  ]
}
</script>

Then on each service page, add a Service block that points back to the business by its @id:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Service",
  "serviceType": "Water heater replacement",
  "provider": { "@id": "https://www.example.com/#business" },
  "areaServed": { "@type": "City", "name": "Frisco, TX" },
  "url": "https://www.example.com/water-heater-replacement/"
}
</script>

A few rules I follow:

  1. sameAs only lists profiles that exist and are yours: Facebook, Yelp, BBB, your Google Maps link.
  2. Name, phone and address match your Google Business Profile character for character.
  3. No aggregateRating for your Google reviews. Google doesn’t show review stars for a business marking up its own reviews, and made up or invisible ratings are how you earn a manual action.

Step 3: Test it

  1. Deploy, then paste the page URL into Google’s Rich Results Test. You want it to detect a local business with no critical errors.
  2. Run the same URL through validator.schema.org. Google’s tool only checks what Google uses. The Schema.org validator checks everything else, like areaServed and sameAs.
  3. In Search Console, use URL Inspection → Request Indexing so Google picks up the change sooner.

Have Claude write yours

Write LocalBusiness JSON-LD for my homepage. Use the most specific
schema.org subtype for a [trade]. Business facts: [name, phone, full
address, hours, website]. Cities I serve: [list]. Profiles for sameAs:
[URLs]. Give it an @id of [site]/#business. Then write one Service
block per service page that references that @id: [list pages].
No aggregateRating. Don't invent any fact I didn't give you.

One honest warning

Schema has to describe what’s actually on the page and on your profile. If the markup says you serve 30 cities and the page names three, you’re telling Google two different stories. Google’s guidelines say markup should reflect content visible to the user, so keep the two identical.

Check Whether ChatGPT Names Your Business, Then Fix It

The exact prompts I use to see if ChatGPT, Perplexity and Google's AI recommend a local business, and the fixes that make you easier for them to name.

aeochatgptai search Updated Sep 29, 2026
Read the AI visibility report ↗

People now type “who’s a good roofer in Plano” into ChatGPT instead of Google. The AI names two or three companies and the rest don’t exist for that customer. Most owners have never checked whether they’re one of the names.

This takes about 30 minutes, and you should do it before you change anything.

Step 1: Run the test prompts

Open a private window and log out where you can, so your own history doesn’t skew the answers. Then run these in ChatGPT, Perplexity, Google (the AI Overview or AI Mode) and Gemini:

Who's the best [trade] in [city]?
I need a [trade] near [neighborhood]. Who should I call?
Recommend a reliable [trade] in [city] with good reviews.
Best company for [specific job, like a water heater swap] in [city]?
Is [your business name] legit? What do people say about them?

For investors, swap in “Who buys houses for cash in [city]?” and “Is [your name] a legit cash buyer?”

Write down four things for each answer: were you named, where in the list, what it said about you, and which source it cited. The source matters. If it cites Yelp or a directory instead of your site, that tells you where the AI is getting its facts.

Step 2: Make sure everything says the same thing

AI tools cross check. If your Google profile says “Sample Street Plumbing LLC,” your site says “Sample St. Plumbing” and your Yelp page has an old phone number, the AI is less confident you’re one business and hedges toward a competitor.

Make sure your name, phone, address and service list match exactly on your website, Google Business Profile, Bing Places, Apple Business Connect, Yelp, Facebook and BBB. Bing Places matters more than people think, since Microsoft Copilot answers from Bing.

Step 3: Get reviews that describe real jobs

Reviews that say “replaced our water heater in Frisco, showed up same day” give an AI something specific to repeat. You can’t tell customers what to write (Google’s policy prohibits asking for specific content), but you can ask everyone, and replies are yours: mention the job and the town naturally when you respond.

Step 4: Answer questions on your own pages

Add a visible FAQ to your service pages using the questions from Step 1 and the ones customers ask on the phone. Answer in the first sentence, then explain. AI tools lift short, direct answers.

Google stopped showing FAQ rich results in May 2026, so do this for readers and AI, not for a search feature.

Step 5: Get mentioned somewhere other than your own site

The AI trusts what other sites say about you. Local chamber listings, trade associations, supplier “find an installer” pages, a local news mention, a sponsorship page. One real mention beats fifty junk directory listings.

Step 6: Don’t block the crawlers

Open yoursite.com/robots.txt. If it blocks OAI-SearchBot or PerplexityBot, you’ve opted out. OpenAI’s docs say sites that block OAI-SearchBot won’t be shown in ChatGPT search answers.

When RankGrid measured these signals across 13,579 DFW contractor profiles, 55% of the 10,828 websites we checked had no local schema on the homepage, and 29% of the contractors had no working website at all. The bar is low.

One honest warning

AI answers change from one run to the next, and nobody can promise you’ll be named. Save your prompts, re-run the same ones every month, and track the trend. Anyone selling a guaranteed ChatGPT mention is selling something they can’t control.

Why You Rank #2 at the Shop and Vanish 3 Miles Away

How a map scan shows where you actually rank across your service area, how to spot check it free from your desk, and when a paid tool is worth it.

mapsrankingscontractors Updated Sep 29, 2026
Run the free SEO audit ↗

Every owner I talk to has searched their own trade on their phone, seen themselves at #2, and figured they’re fine. Then a customer across town says they couldn’t find you.

Both are true. Google says local results are based on relevance, distance and prominence. Distance means the results change depending on where the person searching is standing. You search from your shop or your house, which is exactly where you look best. A homeowner three miles east might see three competitors and never scroll far enough to see you.

How a map scan works

A map scan picks one keyword, drops a grid of points over your service area (7 by 7 is common, so 49 points), and checks where you rank in the map results from each point. Then it colors them: green where you’re top three, yellow in the middle, red where you’re buried or missing.

What you get is a picture of your real coverage. Usually it’s a green blob around your address that fades out, with dead zones in exactly the towns you want work from.

Spot check it free with Chrome

You can do a rough version by hand. It takes about 20 minutes for one keyword.

  1. In Google Maps, right click a spot in the neighborhood you want to check. The first line in the menu is the latitude and longitude. Click it to copy.
  2. Open a Chrome incognito window and open DevTools (Cmd+Option+I on Mac, Ctrl+Shift+I on Windows).
  3. Press Cmd+Shift+P (or Ctrl+Shift+P), type sensors, and pick Show Sensors.
  4. Under Location, choose Other and paste in the coordinates.
  5. Search your keyword on google.com, like water heater repair, and allow location if it asks. Note where you land in the map results.

Make sure you check at least nine spots: your address, then about 3 miles and 6 miles out in each direction. Write the ranks down in a simple table. From there you’ll see the pattern.

Two other free checks worth a look: in your Google Business Profile, Performance shows the searches people used to find you, and you can drag the Google Maps view over a neighborhood and search from there for a quick rough read.

When a paid tool is worth it

Tools like Local Falcon and BrightLocal run the full scan for you and save the history. Local Falcon charges in credits, one per point, so a single 7 by 7 scan on one keyword uses 49.

It’s worth paying when you track several keywords every month, or when you’re making changes and want proof they moved anything. If you just want to know where you stand once, the manual check does the job.

If you want a quick outside look at the website side, the free audit at audit.rankgrid.ai checks the basics that feed all of this.

One honest warning

You can’t out optimize distance. If your shop is in Frisco, no amount of work will put you in the map pack for someone searching in south Fort Worth. For towns far from your address, the realistic plays are service area pages that rank in the regular results and paid ads. A map scan is also one keyword on one day, so run it again before you panic about a single red dot.

Get Google Reviews at a Steady Pace, Not in Bursts

The text I send after every job, where to get your direct review link, how to reply so the review works for you, and why a steady pace beats a big push.

reviewsgbpcontractors Updated Sep 29, 2026

Most contractors get reviews in bursts. Somebody reads an article, texts 40 old customers in one night, gets 15 reviews, and then nothing for four months. That pattern doesn’t help you much.

Google says it directly in its help docs: more reviews and positive ratings can help your local ranking. What local SEO people have watched for years is that recency counts too. Sterling Sky has published cases where a business’s map rankings slid after new reviews stopped and came back when they started again. The shorthand in the industry is the “18 day rule”: don’t go more than about three weeks without a new review. Treat that as a rule of thumb, not a Google number. The point is a pace.

For context, when RankGrid pulled 13,579 DFW contractor profiles, the median had 33 reviews and 45% had fewer than 25. A steady one or two a week moves you past most of your market within a year.

  1. Search your business name on Google while logged into the account that manages the profile.
  2. Click Ask for reviews (in Google Maps it’s under Reviews → Get more reviews).
  3. Copy the link. Save it in your phone notes. You can also make a QR code from a computer browser.

Sending the direct link matters. Asking someone to “look us up on Google” adds steps, and every step loses people.

Step 2: Send the ask by text, same day

Text within a few hours of finishing, while they’re still happy about the job:

Hey [Name], it's [Your name] with [Business]. Thanks again for
having us out for the [job] today. If you have a minute, an honest
Google review would help us a lot: [link]

If they don’t leave one, send one follow up two or three days later. Then stop. If you run GoHighLevel, the review request workflow sends both for you.

Step 3: Send it to every customer

Google’s review policy is specific. You can ask for reviews. You can’t offer anything for them, you can’t pick only the happy customers, and you can’t pressure people on site. So no “rate us 1 to 5 first” funnel that only sends the 5s to Google. Same text, every job, after you’ve left.

Step 4: Reply to every review with the job and the town

Replies are yours to write, so this is where the service and the town go in naturally:

Thanks, Karen. Glad the water heater swap in Allen went smoothly
and that you had hot water by dinner. Call us anytime.

For a bad review, keep it short and calm: say you’re sorry it happened, and ask them to call you directly so you can make it right. Future customers read your reply, not just the complaint.

Step 5: Track the gap

Keep one date somewhere you’ll see it: when your last review came in. If it’s been two weeks, look at last week’s finished jobs and send the text to anyone you missed.

One honest warning

It’s tempting to tell customers “mention the roof and that you’re in Plano.” Don’t. Google’s policy says businesses shouldn’t request that specific content be included in a review, and scripted reviews read fake anyway. Let them write it their way. Your reply is where the keywords belong.

City Pages That Rank Without Being Doorway Pages

What each city or service page needs so Google indexes it and a customer trusts it, the swap test I run before publishing, and how many pages to start with.

seocontentcontractors Updated Sep 29, 2026

The old play was simple. Write one “Roofing in [City]” page, copy it 30 times, swap the city name, publish. Google’s spam policies name this directly: pages targeted at specific cities that funnel users to one page are doorway abuse, and mass producing pages that add nothing is scaled content abuse. It doesn’t matter whether a person or an AI wrote them.

What usually happens now is quieter than a penalty. Search Console shows the pages as Crawled, currently not indexed. Google looked, decided they weren’t worth keeping, and moved on.

This hits investors hard. Of the 943 Texas investor sites RankGrid checked, almost 1 in 5 ran on the same template. To Google that looks like the same page with the city swapped.

The swap test

Before you publish a city page, take out the city name and put in the next town over. If every sentence is still equally true (the projects, the photos, the advice), it’s a doorway page. Don’t publish it yet.

What each page needs to be its own page

  1. A real job in that city. Before and after photos, the neighborhood, what you did, how long it took.
  2. A review from a customer in that city. Quote it on the page with their first name and town.
  3. Local facts only someone working there knows. Which city office handles permits, HOA rules in the big subdivisions, the age of the housing stock, soil or hail or hard water problems.
  4. Plain service details for that area. Which services you offer there, typical response time, whether there’s a trip charge.
  5. Questions people in that town actually ask, answered in a short FAQ.
  6. Links. From your service area hub page and from the matching service pages, and back out to them.

The title and H1 carry the service and city, like “Water Heater Repair in Allen, TX.” After that, write for the customer.

How many to start with

Start with three to five cities where you have real jobs and real reviews. Add another city when you have new proof from it, not before. Google lets you list 20 service areas on your profile. That isn’t a reason to build 20 pages.

A simple structure that works:

/services/water-heater-repair/
/service-areas/                  (hub, links to every city page)
/service-areas/allen-tx/
/service-areas/mckinney-tx/

Have Claude draft from your real notes

The facts have to come from you. Claude is good at turning your notes into a clean page:

Draft a service area page for [trade] in [city, state]. Use ONLY
these facts: recent job: [what, where, photos I have]. Customer
review: [paste]. Local details: [permits, HOAs, housing age,
weather problems]. Services offered there: [list]. Response time:
[x]. Write an H1 with service + city, 400 to 600 words, a 4 question
FAQ from these questions: [list]. If a fact is missing, leave a
[TODO] instead of inventing it.

One honest warning

City pages won’t put you in the map pack for a town that’s far from your address. Distance is its own factor. What good city pages do is rank in the regular results under the map and convince the person who lands there. If you’re getting no real work from a city yet, you don’t have the material for a good page there anyway.

Set Yourself Up for a Google Knowledge Panel

How I set up the entity signals Google uses to recognize a person, with an about page, Person schema, sameAs links, Crunchbase and Wikidata, plus what went wrong.

entityschemapersonal brand Updated Sep 29, 2026
See my entity home page ↓

A knowledge panel is the box on the right side of Google when someone searches your name. For an operator, a founder or an investor raising money, it answers “is this person real” before anyone calls you.

Nobody can make one for you. Google’s own help page says it doesn’t manually create knowledge panels. What you can do is make it easy for Google to connect your site and your profiles and confirm they all describe the same person. That’s the whole job.

Step 1: Build an entity home page

Pick one page on your own site that is the official “who is this person” page. Mine is mironbriley.com/about/. Keep it factual: full name, what you do, the companies you run and your exact role at each, where you’re based, a short bio. Every fact on it should match what your LinkedIn and other profiles say, word for word where you can.

Step 2: Add Person schema with sameAs

This is the part that ties everything together. The sameAs list tells Google “these profiles are the same person as this page.” Here’s the shape, with made up values:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Person",
  "@id": "https://www.example.com/about/#person",
  "name": "Jane Example",
  "url": "https://www.example.com/about/",
  "jobTitle": "Founder of Example Roofing",
  "worksFor": { "@type": "Organization", "name": "Example Roofing", "url": "https://www.example.com/" },
  "sameAs": [
    "https://www.linkedin.com/in/janeexample",
    "https://www.facebook.com/janeexample",
    "https://www.youtube.com/@janeexample",
    "https://www.crunchbase.com/person/jane-example"
  ]
}
</script>

My about page points to my LinkedIn, Facebook, YouTube, X, Nextdoor and Crunchbase profiles this way. Only list profiles that exist and are clearly you.

Step 3: Crunchbase

Make a free Crunchbase account and create a Person profile. Put your entity home URL in the website field and add your LinkedIn and other socials. Then add that Crunchbase URL back into your sameAs.

Step 4: Wikidata, carefully

Wikidata is a public database of facts that search engines and AI tools read. Items have to meet its notability policy, which in practice means the person can be described using serious, publicly available references. Your own website isn’t enough.

I learned that one directly. I built a Wikidata item for myself, referenced to my own site, and it was deleted in September 2026 for not meeting the notability policy. If you don’t have press coverage, podcast interviews or other independent sources yet, skip Wikidata for now and come back when you do.

Step 5: Close the loop and request a crawl

Once every profile exists, make sure each one points at your entity home, and your entity home lists every one of them. Rebuild and deploy, then check the live page actually has the new links:

curl -s https://www.example.com/about/ | grep sameAs

In Search Console, run URL Inspection on the page and click Request Indexing.

If a panel shows up later, use Claim this knowledge panel at the bottom of it. Once you verify your identity, you can suggest changes.

One honest warning

This can take months, and it may never produce a panel. Google decides. Anyone selling a guaranteed knowledge panel is promising something Google says it doesn’t do on request. What you control is being consistent and findable, and that helps you in regular search and AI answers even if the panel never shows.

How I Ship Fast Local Sites on Free Hosting

Why speed matters for a local business site, and the exact setup I use to build one in Astro, host it free on Cloudflare and check it in PageSpeed Insights.

astrocloudflarepagespeed Updated Sep 29, 2026
Test your site in PageSpeed Insights ↗

Most people who find a contractor are on a phone, often on a weak signal in a driveway. If your site takes eight seconds to show anything, they hit back and call the next result. When RankGrid checked 10,828 DFW contractor websites, 11% didn’t load at all. Slow is the step before broken.

Google does use page experience as a signal, but relevance still wins, and a fast site won’t outrank a better answer. The bigger reason to be fast is the customer who’s already on your page.

Why I build static

Most small business sites are a WordPress install with a theme, a page builder and a stack of plugins. Every page gets built on the server when someone asks for it, and every plugin is something to update.

A static site is plain HTML files built ahead of time. Nothing to log into, no database, nothing to patch. I use Astro because it outputs plain HTML and ships no JavaScript unless you add it.

Step 1: Make the site

You need Node.js 22.12 or newer. Then:

npm create astro@latest
cd your-project
npm run dev

The setup asks a few questions. Pick the basic template if you’re starting blank. When the pages are ready, build it:

npm run build

Your finished site lands in the dist folder.

Step 2: Host it on Cloudflare for free

Cloudflare doesn’t charge for requests to static files, so a local business site costs nothing to host. From the project folder:

npx wrangler login
npx wrangler pages project create my-site
npx wrangler pages deploy dist --project-name my-site

You’ll get a my-site.pages.dev address right away. To use your own domain, open the project in the Cloudflare dashboard under Workers & Pages, go to Custom domains, and add it.

Step 3: Check it in PageSpeed Insights

Paste your URL into pagespeed.web.dev and look at the Mobile tab first. Google’s Core Web Vitals targets, which it wants at least 75% of real visits to hit:

  1. LCP (main content shows up): 2.5 seconds or less.
  2. INP (page responds to a tap): 200 milliseconds or less.
  3. CLS (layout doesn’t jump around): 0.1 or less.

A new site won’t have real user data yet, so you’ll only see the lab test. That’s fine for now.

If the score is low, it’s almost always images. Convert photos to WebP, set a width and height on every image, and add loading="lazy" to anything below the first screen.

Have Claude Code do the speed pass

Go through this Astro site and make it fast on mobile. Convert
images to WebP at no more than 2x their display size, add width
and height to every img, lazy load everything below the fold,
preload the hero image, and remove any font weights we don't use.
Then build it and list what changed.

One honest warning

Cloudflare now recommends Workers over Pages for brand new projects, and Astro’s docs show that route (npx wrangler deploy with a small config file). Pages still works and it’s what I use, but check the current docs before you start. Also, a static site has no built in contact form. You’ll need to wire one up yourself, which is exactly what the form to CRM webhook walkthrough covers.

GoHighLevel + Automation 7

Build GoHighLevel Workflows From Claude Code

What works for getting Claude to build GoHighLevel automations: the official MCP server, HighLevel's AI builder, and a community repo that uses the internal API.

gohighlevelclaudemcpworkflows Updated Sep 29, 2026
See the repo on GitHub ↗

GoHighLevel’s public API can list your workflows, but it can’t create or edit one. So when somebody says “Claude built my workflow,” one of three things is going on. They used HighLevel’s own AI builder, they used the official MCP server for everything around the workflow, or they’re calling the internal API the web app uses.

Here’s how each one works, and which one I’d reach for first.

Option 1: Connect the official HighLevel MCP server

HighLevel runs its own MCP server. Their help doc for Claude gives this command for Claude Code:

claude mcp add --transport http leadconnector https://services.leadconnectorhq.com/mcp/anthropic/v2

Then run /mcp inside Claude Code and finish the HighLevel sign-in. The connection only sees the sub-accounts you pick during that sign-in.

If you’d rather use a token, create one in the sub-account under Settings → Private Integrations, then send it as an Authorization: Bearer header plus a locationId header to https://services.leadconnectorhq.com/mcp/. HighLevel notes the token route gets fewer scopes than the sign-in route.

It’s good for contacts, tags, conversations, opportunities and calendars, which is everything a workflow touches. HighLevel’s docs don’t list building workflows as something it does.

Option 2: The built-in AI builder

On the Workflows list there’s a Build using AI button. Describe the workflow in plain words and it drafts the trigger and actions. This is the supported way to get a workflow from a prompt, and it’s where I’d start. Have Claude Code write the prompt:

Write a prompt for GoHighLevel's workflow AI builder. Goal: when a
quote form is submitted, text the lead within a minute, notify me by
SMS, wait 10 minutes for a reply, and if none, send a second text.
Include the exact messages. Keep each text under 160 characters.

Option 3: The ghl-automation-builder repo

drleadflow/ghl-automation-builder is someone else’s public repo, not mine. The author reverse-engineered the internal API behind the HighLevel web app and documented it: 95 action types, 93 trigger types, schemas and example scripts. The README describes 16 MCP tools for create, edit, publish and delete, but those run on the author’s own Cloudflare Worker. They aren’t something you install from the repo.

The setup, from the repo’s scripts/README.md:

git clone https://github.com/drleadflow/ghl-automation-builder.git
cd ghl-automation-builder
npm install
npx playwright install chromium   # only if Chrome CDP isn't available
export GHL_FIREBASE_REFRESH_TOKEN="..."

The token comes from your own logged-in browser session. docs/auth.md and scripts/refresh-token.sh walk through it. From there, point Claude Code at the docs:

Read docs/api-reference.md and verified/confirmed-type-strings.md.
Using my location ID [paste], create a draft workflow in a test
folder: trigger Contact Tag added "new-lead", then Send SMS, Wait 5
minutes, Send Internal Notification. Do not publish it.

One honest warning

Option 3 isn’t supported by HighLevel. That session token carries your full user permissions, the endpoints can change without notice, and the README says the author’s own token only covers their test account. The repo also has no license file. Use it on a throwaway sub-account, never on a client’s live account, and open every workflow in the builder before you publish it.

Send Any Website Form Into GoHighLevel With One Webhook

The exact pattern I use to wire a form on any site (Astro, plain HTML, Cloudflare Pages) into a GoHighLevel workflow. No Zapier, no API key in the page.

gohighlevelwebhookformscloudflare Updated Sep 29, 2026

Every site I build has a form, and every form has to land in the CRM with the right tags before anybody follows up. A lot of people pay for Zapier to do this. You don’t need it.

What you want to do is point the form at a GoHighLevel Inbound Webhook trigger. The webhook URL is the only thing the page needs, and it’s not a secret key, so it can’t be used to read your account.

Step 1: Create the webhook trigger

  1. In GoHighLevel, go to Automation → Workflows → Create Workflow → Start from scratch.
  2. Add a trigger and pick Inbound Webhook.
  3. Copy the URL it gives you. It looks like https://services.leadconnectorhq.com/hooks/.../webhook-trigger/....

Leave that tab open. You’ll come back to map the fields.

Step 2: Post the form to it

This is plain JavaScript. It works on any static site.

<form id="lead-form">
  <input name="first_name" required>
  <input name="email" type="email" required>
  <input name="phone">
  <button>Send</button>
</form>
<script>
document.getElementById('lead-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const data = Object.fromEntries(new FormData(e.target));
  data.source = location.pathname;
  data.submitted_at = new Date().toISOString();
  await fetch('YOUR_WEBHOOK_URL', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  });
  location.href = '/thank-you/';
});
</script>

Submit the form once with test data. Go back to the trigger and hit Fetch sample request so GoHighLevel knows your field names.

Step 3: Build the workflow behind it

Make sure you add these in order:

  1. Create Contact and map first_name, email, phone from the webhook data.
  2. Add Tag with something specific to the form, like quote-form-optin. The tag is how you’ll find these people in six months.
  3. Whatever follow-up you want: a text within a minute, an internal notification, an email drip.

Publish it. That’s basically it.

Why I send the source field

When you have six forms on six pages, you’ll want to know which page the lead came from. Passing location.pathname costs nothing and saves you from guessing later.

Have Claude Code do it

If the site lives in a folder Claude Code can see, you can skip the typing:

Add a lead form to the contact page. POST first_name, email, phone,
source and submitted_at as JSON to this webhook: [paste URL].
Redirect to /thank-you/ on success. No API keys in the page.

One honest warning

A webhook URL in public code can be spammed. If you start getting junk contacts, put a hidden honeypot field in the form and skip the request when it’s filled, or route the POST through a small serverless function first (Cloudflare Pages Functions works) and check it there.

A Speed-to-Lead Workflow That Texts Back in Under a Minute

The GoHighLevel workflow I'd build for any contractor or investor: an instant text to the lead, an alert to the owner, and a path that keeps trying if nobody replies.

gohighlevelspeed-to-leadsmsworkflows Updated Sep 29, 2026

Most leads don’t go cold because you’re bad at sales. They go cold because you were on a roof when the form came in and saw it 90 minutes later. I wrote about that gap in Speed to Lead. This is the workflow that closes it.

What you want is simple. The lead gets a text from your business number within a minute, you get a text telling you to call, and if they don’t answer, the system keeps trying so you don’t have to remember.

Step 1: Set the trigger

  1. Go to Automation → Workflows and create a workflow from scratch.
  2. Add a Form Submitted trigger and pick your quote form.
  3. If leads also come from Facebook ads, add a second trigger: Facebook Lead Form Submitted. If your form lives off GoHighLevel, use Inbound Webhook (see Send Any Website Form Into GoHighLevel).

Step 2: Text the lead right away

Add Send SMS as the first action, with no wait before it.

Hi {{contact.first_name}}, this is {{location.name}}. Got your
request. I'm on a job right now, is it OK if I call you in the
next 15 minutes?

For investors:

Hi {{contact.first_name}}, got your info about the property. Is
now a good time for a quick call, or is later today better?

End on a question. It gives them an easy reason to reply. No links in the first text.

Step 3: Tell the owner

Add Send Internal Notification, set the type to SMS, and send it to whoever picks up the phone:

New lead: {{contact.first_name}} {{contact.last_name}}
{{contact.phone}}. Call now.

Step 4: Branch on the reply

  1. Add a Wait step and choose The contact to reply, channel SMS.
  2. Turn Timeout on and set it to 10 minutes. The step now splits into a reply path and a timeout path.
  3. On the reply path, add another Send Internal Notification: “{{contact.first_name}} replied. Check conversations.”
  4. On the timeout path: Send SMS, then Wait 1 day, then one last Send SMS and a Send Email.

Second text:

{{contact.first_name}}, still want that estimate? Reply with a
good time and I'll call you then.

Last text, the next day:

Last check from me. If you already found someone, no problem. If
not, reply YES and I'll call today.

Step 5: Settings, then publish

Open the Settings tab. Leave Allow Re-entry off so a double form submit doesn’t send two texts. A Time Window keeps texts inside business hours, but it applies to every message in the workflow, including the first one. A lead at 10pm gets their text when your window opens. For most businesses that’s fine.

Publish it, then fill out your own form from your phone and time how long the text takes.

One honest warning

Leave Stop on Response off in this workflow. The reply path is already handling replies, and if both are on, a reply can end the workflow before your “they replied” alert goes out. Also, none of this texts anyone until your number is A2P 10DLC registered. The missed call walkthrough covers what that involves.

Missed Call Text Back in GoHighLevel (and the A2P Catch)

Two ways to text back every missed call to your business line in GoHighLevel, which trigger to use, and the registration step that has to happen first.

gohighlevelmissed-callssmsa2p Updated Sep 29, 2026

A missed call is a lead with their hand up. Contractors miss calls all day because they’re working. Investors miss the seller who called at 7pm, and that seller calls the next number on Google. A text back within a minute keeps them from doing that.

GoHighLevel gives you two ways to set this up. Pick one. Running both sends two texts.

Option A: The built-in setting

  1. Go to Settings → Phone System, open the Voice section, then Voicemail & Missed Call Text Back.
  2. Turn on Missed Call Text Back and write the message.
  3. Put your cell in the test field and hit Send Test.

It fires when a call rings past your incoming call timeout without being answered. HighLevel suggests 10 to 20 seconds for that timeout. Answered calls never trigger it.

This is the fastest setup. The downside is that it’s one text and done. No owner alert, no tag, no follow-up.

Option B: A workflow

  1. Go to Automation → Workflows and start from scratch.
  2. Add the Call Details trigger. Older tutorials call it Call Status.
  3. Set Call Direction to incoming and the call status to not answered. Add busy and voicemail if you want those covered too.
  4. Add Send SMS:
Hey, this is {{location.name}}. Sorry I missed your call, I'm on
a job. What can I help you with? I'll call you back shortly.

For investors:

Hi, sorry I missed you. Are you calling about a property? Send
me the address and I'll call you right back.
  1. Add Add Contact Tag with missed-call.
  2. Add Send Internal Notification by SMS to whoever returns calls: “Missed call from {{contact.phone}}. Call back.”

HighLevel’s docs say this trigger fires on each status change. If one call sends two texts, tighten the status filter so only one status matches.

If calls forward to your cell

When your HighLevel number forwards to your personal phone and your cell’s voicemail picks up, the call gets logged as completed. No missed call, no text. The fix is Call Connect:

  1. Settings → Phone System, click the three dots next to the number, then Edit Configuration.
  2. Open Advanced Settings and turn on Call Connect.

Now you press a key to accept each call, so your voicemail answering doesn’t count as a pickup.

The A2P 10DLC catch

In the US, business texts from a local 10-digit number need A2P 10DLC registration. That’s a carrier requirement, not a HighLevel one. It has two parts: a Brand (who you are) and a Campaign (what kind of texts you send). You’ll find it under Settings → Phone System → Trust Center. Toll-free numbers go through toll-free verification instead.

One honest warning

Registration isn’t instant, and campaigns get rejected over small things. A website with no privacy policy, or a form with no SMS consent language, are common ones. Get approved before you build any of this. Otherwise you’ll test a workflow that looks perfect and never actually sends.

Ask for the Google Review the Day the Job Wraps

A GoHighLevel workflow that sends a review ask by text and email when a job is marked complete, sends one reminder, and stops once they click or reply.

gohighlevelreviewsgoogle-business-profileworkflows Updated Sep 29, 2026

The best time to ask for a review is the day the job is done, while the customer is still looking at the clean floors or the new roof. Most owners know this and still forget, because by 5pm they’re thinking about tomorrow. So let the pipeline ask for you.

Reviews are one of the signals Google uses for the map pack, and they’re what a homeowner reads before calling. A steady trickle beats a burst every six months.

  1. In your Google Business Profile, use the option to ask for reviews and copy the short link. It opens the review box directly, so the customer doesn’t have to hunt for your listing.
  2. In GoHighLevel, go to Marketing → Trigger Links → Add Link, name it google-review, paste the link and save.

Use the trigger link in your messages, not the raw Google link. That’s how GoHighLevel knows who clicked.

Step 2: Pick the trigger

Either one works:

  1. Pipeline Stage Changed, with the pipeline filter set to your jobs pipeline and the stage set to your last stage (Job Complete, Closed, whatever you call it).
  2. Contact Tag added, tag job-complete, if you don’t run jobs through a pipeline.

Heads up on the first one: if a job moves backward and then forward again, the trigger fires again. Leave Allow Re-entry off so nobody gets asked twice.

Step 3: The ask

Add Send SMS:

Hi {{contact.first_name}}, thanks for having us out. Would you
mind leaving us a quick Google review? Takes about a minute:
[trigger link]

Then Send Email with the same link and a line or two more. Keep the email plain. It should look like it came from you, not a marketing department.

Step 4: One reminder, then stop

  1. Add a Wait of 2 days.
  2. Add If Else and check whether the contact has the tag review-clicked. If they do, the workflow ends there.
  3. If they don’t, one last Send SMS: “Hi {{contact.first_name}}, in case the link got buried: [trigger link]. Thanks again.”

To set that tag, build a tiny second workflow: Trigger Link Clicked trigger, filtered to google-review, then Add Contact Tag review-clicked.

In the main workflow’s Settings tab, turn on Stop on Response. Anyone who replies, whether it’s “done!” or “actually, there’s a problem,” drops out and you handle it yourself.

HighLevel also has a built-in Send Review Request action that uses the message from its review settings. It works fine. I’d still write the text myself so every word sounds like the business.

One honest warning

Don’t filter who gets the ask. Google’s review policy doesn’t allow asking only the happy customers, and it doesn’t allow giving anything in exchange for a review. Send it after every completed job. And when a reply says “there’s a problem,” that’s worth more than the review. Make sure a person sees it the same day.

Text Your Old Leads Back Into Conversations

A GoHighLevel reactivation campaign for dead leads: tag the list, send one short plain question, route replies to a person, and stay inside the texting rules.

gohighlevelreactivationsmscompliance Updated Sep 29, 2026

Every contractor and investor I know is sitting on a list of people who asked for a quote, or said “not yet,” and never heard from them again. Those people already know your name. One short text with one question can restart the conversation for the cost of an SMS.

Step 1: Build the list

  1. In Contacts, filter for people who came in as leads but never turned into a job or a deal. A good start: created more than 90 days ago, no appointment, not marked won.
  2. Take out anyone with DND on, anyone who has opted out, and current customers.
  3. Select the rest and add one tag: reactivate-oct26. A dated tag lets you tell campaigns apart next year.

Only text people who gave you their number. A purchased or skip-traced list isn’t a reactivation list, and texting one is how numbers get flagged.

Step 2: The workflow

  1. Trigger: Contact Tag added, reactivate-oct26.
  2. First action: Drip Mode, so it sends in small batches (something like 25 at a time, an hour apart) instead of all at once.
  3. Then Send SMS.

In the Settings tab, set a Time Window (weekdays, 10am to 6pm is a safe start), set the timezone to the contact’s timezone if your list spans states, and turn on Stop on Response.

Step 3: The text

Short, plain, no link, no pitch. One question.

For a service business:

Hi {{contact.first_name}}, it's [your name] with [company]. You
asked about a quote a while back. Is that still something you're
thinking about?

For investors:

Hi {{contact.first_name}}, this is [your name]. We talked a while
back about the property on [street]. Are you still thinking about
selling?

Add “Reply STOP to opt out” at the end, or turn on Make SMS compliant by adding an opt-out message under Settings → Phone System → Messaging so it’s added for you.

Step 4: Handle the replies

Build a second workflow:

  1. Trigger: Customer Replied, filtered to the reactivate-oct26 tag and the SMS channel.
  2. Send Internal Notification to you by SMS.
  3. Create/Update Opportunity in your main pipeline so the reply doesn’t live only in the inbox.

Replies come in three kinds: yes, not now, and stop. Call the yeses the same day. For “not now,” ask when, and set a task for that date.

Before you send to the real list, text STOP to your business number from your own phone and confirm your test contact flips to DND. GoHighLevel’s messaging settings list STOP, CANCEL, UNSUBSCRIBE and a few others as opt-out words, but check it yourself.

One honest warning on the rules

Federal rules put marketing texts between 8am and 9pm in the recipient’s local time, and some states are tighter. Florida, for example, is 8am to 8pm. If your list is old, expect wrong numbers and a few annoyed replies. That’s normal. Send slow, answer every reply, and if you do a follow-up text, one is enough.

GoHighLevel Snapshots: What They Carry and How to Load One

What a GoHighLevel snapshot copies and what it leaves behind, how to import one and load it into a sub-account, and where my niche guides fit in.

gohighlevelsnapshotssetup Updated Sep 29, 2026

A snapshot is a copy of a GoHighLevel sub-account’s setup. You build one account the way you like it, snapshot it, and load it into the next account so you’re not rebuilding workflows and pipelines from zero.

The part people learn the hard way is what a snapshot doesn’t carry.

What comes over and what doesn’t

Per HighLevel’s docs, a snapshot copies configuration: workflows, Conversation AI, pipelines, custom fields, tags, smart lists, funnels, forms, email templates, calendars and reports.

It doesn’t copy contacts, conversations, appointments, reputation data, Stripe connections or third-party integrations. You’ll still buy a phone number and get it registered for texting in the new account. So a snapshot gets you the skeleton. You connect the rest.

How to import one

You need an agency account for this. Imported snapshots live at the agency level, not inside a sub-account.

  1. Sign in to your HighLevel agency, then open the snapshot share link in the same browser.
  2. Rename it if you want and click Import Now. It shows greyed out until processing finishes.
  3. From Agency View, find the sub-account, open its menu and pick Manage Client.
  4. Click Actions, then Load Snapshot, choose the snapshot, and pick which assets to bring in.
  5. Review the conflicts screen, then confirm.

Importing puts it in your agency library. Loading is what puts it in an account. They’re two separate steps, and people forget the second one.

Check the load with Claude Code

If you’ve connected HighLevel’s MCP server (see Build GoHighLevel Workflows From Claude Code), have Claude look it over:

List the custom fields and the pipelines with their stages in this
sub-account. Flag duplicates, and anything that still names the
business this snapshot was built for.

Leftover names from the original business are the most common thing I’d expect to find, and a customer will notice them before you do.

My niche guides

The posts on my blog with “ghl-snapshot” in the URL aren’t downloadable snapshots. They’re local SEO guides by niche: how that kind of business gets found on Google, and what the site needs before a CRM matters.

  1. Cleaning companies: the map pack versus organic results, and the service plus city searches that book cleans.
  2. Real estate agents: neighborhood and seller searches the portals don’t bother to own.
  3. Real estate investors: how motivated sellers search and why most template investor sites never rank.
  4. Professional service firms: accountants, attorneys and advisors, and why search backs up referrals.
  5. Any local business: the four layers of a lead site that ranks.

Read the one for your niche before you load anything. A snapshot moves leads through a pipeline. It doesn’t bring them in.

One honest warning

Loading into an account that already has workflows and fields can collide with what’s there. HighLevel shows you the conflicts before you confirm, so read that screen. Better yet, load into a fresh test sub-account first, click through everything, then decide what goes into the live one.

Tools I Use 7

Firecrawl MCP: Pull a Whole Website Into Claude Code

How I use Firecrawl inside Claude Code to scrape a client's old site or a competitor's service pages before I rebuild anything.

firecrawlmcpscrapingclaude-code Updated Sep 29, 2026
Firecrawl MCP on GitHub ↗

Before I rebuild a contractor’s website, I want every word that’s on the old one. The service list, the city pages, the about copy, the phone number they forgot they changed. Copying that out of a browser by hand eats an afternoon.

Firecrawl is a scraping service with an MCP server, so Claude Code can call it like any other tool. Claude asks for a page, Firecrawl loads it (JavaScript included) and sends back clean markdown Claude can actually work with.

Step 1: Add the server

Sign up at firecrawl.dev and copy your API key from the dashboard. Then in your terminal:

claude mcp add firecrawl --env FIRECRAWL_API_KEY=fc-YOUR_KEY -- npx -y firecrawl-mcp

If you’d rather sign in through the browser than paste a key, Firecrawl runs a hosted version:

claude mcp add --transport http firecrawl https://mcp.firecrawl.dev/v2/mcp-oauth

Then open Claude Code and run /mcp to finish the sign-in. Either way, make sure firecrawl shows as connected in /mcp before you go on.

Step 2: Map the site before you scrape it

What you want to do is map first. The map tool lists every URL on a domain without pulling the content, so you see how big the job is before you spend credits on it.

Use Firecrawl to map https://oldclientsite.com. Group the URLs into
services, locations, blog and other. Don't scrape anything yet.

Step 3: Scrape only what matters

Scrape every service and location page from that map. Save each one
as markdown in ./old-site/ with the source URL at the top. Then give
me one list of every service they offer and every city they mention.

That list becomes the page plan for the new site. From here I compare it against what the owner told me on the phone, because the old site is almost always missing a service or two they actually do.

Pointing it at competitors

Same pattern, aimed at whoever sits above my client in the map pack:

Scrape the homepage and top 5 service pages of [competitor URL].
Tell me which services they have pages for that we don't, and what
they put in their H1s and title tags.

I also use Firecrawl’s search tool for outreach research, like pulling a list of local news sites and directories in a city before a press or citation push. Search plus scrape in one prompt saves a lot of tab juggling.

One honest warning

Every page costs credits. The free plan gives you 1,000 credits a month and a basic scrape is one credit per page, so one careless crawl of a site with a big blog can burn most of your month. Paid plans start around $16 to $19 a month. Crawls also drag in junk like tag archives and pagination, which is why I map first and tell Claude exactly which URLs to scrape. And some sites block scrapers outright. When that happens, open the page in your own browser and have Claude read it there.

Perplexity MCP: Local Market Research Inside Claude Code

How I use Perplexity inside Claude Code to find who ranks for a service in a city, what competitors promise, and where the gaps are.

perplexitymcpresearchcompetitors Updated Sep 29, 2026
Perplexity MCP on GitHub ↗

Claude Code is great at building and writing. It’s not a search engine, and what it knows stops at its training date. When I need to know which roofers in Plano are winning right now and what they promise on their homepages, I want a current answer with sources attached.

Perplexity’s MCP server gives Claude Code four tools: perplexity_search for ranked results, perplexity_ask for a quick cited answer, perplexity_reason for harder analysis, and perplexity_research for a deep report that can take a few minutes to come back.

Step 1: Get an API key

Go to console.perplexity.ai, add a payment method, load some credits and create an API key. The API is pay as you go on prepaid credits, and it’s billed separately from the regular Perplexity app.

Step 2: Add it to Claude Code

The simplest route is Perplexity’s hosted server:

claude mcp add --transport http perplexity https://api.perplexity.ai/mcp --header "Authorization: Bearer YOUR_API_KEY"

Or run it on your own machine:

claude mcp add perplexity --env PERPLEXITY_API_KEY="your_key_here" -- npx -y @perplexity-ai/mcp-server

Run /mcp inside Claude Code and make sure perplexity shows as connected.

Step 3: Ask who ranks and why

This is the prompt I run most before I pitch or build anything:

Use Perplexity to find who shows up for "water heater repair" in
Frisco, TX. For the top 5 companies, pull their review count, the
promise in their homepage headline, any pricing or guarantees on
the site, and how many city or service pages they have. Cite sources.
Then tell me why you think each one ranks where it does.

The “why” part is where it earns its money. It’ll point at things like review volume, dedicated city pages, or a business that’s been on the same domain for 15 years. That gives me a plan before I’ve opened a single tool.

Step 4: Map the messaging gap

Use perplexity_research to compare how the top 5 [service] companies
in [city] describe themselves. What do they all say? What does
nobody say? Suggest two angles a new competitor could own.

What nobody says is the useful part. If every plumber in town leads with 24/7 service, leading with it too just makes you one more of them.

One honest warning

Treat rankings from Perplexity as a lead to check, never as a fact. It’s reading the web, not a live Google results page, and it will sometimes name a company that isn’t in the map pack at all. When the ranking itself matters, confirm it with a real rank check. Also watch your balance. Every call spends credits, the deep research tool spends the most, and when the credits hit zero the tool just errors out mid-task until you top up.

Playwright MCP: Screenshots, Graphics and Form Tests

How I use Playwright MCP to screenshot client sites for my portfolio, turn HTML layouts into graphics, and test every form after a deploy.

playwrightmcpscreenshotstesting Updated Sep 29, 2026
Playwright MCP on GitHub ↗

Playwright is Microsoft’s browser automation tool. The MCP server lets Claude Code open a real browser, click, type, resize the window and take screenshots. I use it for three jobs, and none of them need me to touch the mouse.

It runs its own browser profile, separate from your everyday Chrome. For testing that’s what you want, because you see the site closer to the way a stranger sees it, not with your logins and cached files.

Install it

claude mcp add playwright npx @playwright/mcp@latest

Restart Claude Code and run /mcp to make sure playwright is connected.

Job 1: Portfolio screenshots

Every client site I finish goes in the portfolio. Instead of screenshotting by hand:

Open each of these URLs at 1440x900. Wait for the page to finish
loading, close any cookie banner, scroll to the bottom and back up,
then save a full-page screenshot to ./portfolio/[domain].png.
Then do a second pass at 390x844 for mobile.

The scroll step matters. Sections that animate in on scroll can come out blank in a full-page screenshot if the browser never scrolled past them.

Job 2: Graphics built in HTML

Comparison tables, pricing cards, before and after layouts. Image models still mangle text. HTML doesn’t. So I have Claude build the graphic as one HTML file at an exact pixel size, then screenshot it.

Build a 1080x1080 comparison graphic as graphic.html: two columns,
[left label] vs [right label], 6 rows, our brand colors and fonts.
Start a local server in this folder with python3 -m http.server 8000,
then screenshot http://localhost:8000/graphic.html at 1080x1080.

Why the local server: Playwright MCP blocks file:// URLs by default and keeps file access inside your project folder. Serving the folder on localhost gets around that without loosening any settings.

Job 3: Test the form after every deploy

This is the one people skip. A form that looks fine and sends nothing loses leads quietly for weeks.

Go to [live URL]/contact/. Fill the form with test data (name
"Test Lead", email test@yourdomain.com, phone 555-555-0100) and
submit it. Tell me what page loads next, list any console errors,
and check the network requests to confirm the form POST returned
a 200.

Then go check your CRM for the test contact, confirm the tags landed, and delete it. If the POST failed or never fired, Claude already has the console errors in front of it to start fixing.

One honest warning

Every page Claude reads through Playwright lands in its context as a structured snapshot, and on a long page that’s a lot of tokens. Microsoft’s own README now says coding agents may do better with their Playwright CLI for exactly that reason. For a handful of screenshots and a form test, the MCP is fine. For crawling 200 pages, write a script instead. And some sites spot automated browsers and throw a CAPTCHA, which Claude can’t solve for you.

Claude in Chrome: Let Claude Code Use Your Logged-In Browser

How I let Claude Code drive my own Chrome to work inside tools that have no API, and to make images with Gemini using accounts I already have.

claude-in-chromebrowsergeminiimages Updated Sep 29, 2026
Claude in Chrome setup docs ↗

A lot of the tools a service business runs on have no API, or keep it locked behind a higher plan. Directory dashboards, supplier portals, the back end of a site builder. Playwright doesn’t help much there, because it opens its own browser that isn’t logged into anything.

Claude in Chrome is Anthropic’s browser extension that connects to Claude Code. Claude opens tabs in your real browser, with your logins, and you watch it work in a visible window.

What you need

  1. Google Chrome or Microsoft Edge. Other Chromium browsers like Brave and Arc get detected too.
  2. The Claude extension from the Chrome Web Store.
  3. A paid Anthropic plan (Pro, Max, Team or Enterprise), signed in with /login. If you run Claude Code on an API key, the Chrome integration stays off.

Step 1: Connect it

claude --chrome

The first time, Claude Code shows a short intro. Press Enter. Run /chrome any time to check the connection. You want to see Status: Enabled and Extension: Installed. If you end up using it daily, pick Enabled by default in that same menu so you can drop the flag.

Step 2: Work inside a tool with no API

Open [dashboard URL] in Chrome. I'm already logged in. Go to the
listings page and, for each location, copy the business name, phone
and hours into listings.csv. Stop and ask me before you change,
save or submit anything.

That last line matters. It’s your real account. I let it read freely and make it ask before anything that saves, deletes or sends.

Step 3: Images with Gemini, in my own session

This is how I make most of my images now. I’m signed into Gemini in Chrome, and Gemini’s image model (Nano Banana) is right there. Claude writes the image prompt, drives Gemini, and I pick the winner.

Open gemini.google.com in Chrome. Ask it to create this image:
[prompt]. Wait for it to finish, then ask for 2 variations with
[what to change]. Tell me when they're ready so I can pick one.

Claude usually writes a sharper image prompt than I would, and I’m using a Gemini account I already have instead of paying for a separate image API. When text has to be exact, like a price table, I skip the image model and build it in HTML instead.

One honest warning

It’s slow next to an API, because it’s really clicking through pages one at a time. It stops at logins and CAPTCHAs and waits for you. A JavaScript pop-up (an alert or confirm box) freezes it until you close the pop-up yourself. Gemini’s image tool also has usage limits that depend on your Google plan, so a big batch can hit the wall halfway. And leaving Chrome enabled by default loads the browser tools into every session, which eats context. I turn it on for the jobs that need it and leave it off the rest of the time.

Humanizer: Strip the AI Tells Out of Claude's Writing

The open source skill I run on every piece of copy before it ships, plus the banned word check I stack on top of it.

humanizerskillscopywritingclaude-code Updated Sep 29, 2026
Humanizer on GitHub ↗

People can spot AI copy fast. The sentence that sets up a contrast nobody asked for. The dramatic one-line closer. Every list with exactly three items. Dashes everywhere. A customer can’t always name what’s wrong, but they feel it, and a contractor homepage that reads like a chatbot doesn’t get the call.

Humanizer is an open-source skill (MIT license) built on Wikipedia’s “Signs of AI writing” guide, the one Wikipedia editors use to catch machine-written text. It checks for 26 patterns and rewrites them without changing what the text says.

Install it

Inside Claude Code:

/plugin marketplace add blader/humanizer
/plugin install humanizer@humanizer

That needs Claude Code 2.1.142 or newer. On an older version, use the Skills CLI from your terminal:

npx skills add blader/humanizer --global --agent claude-code

Installed as a plugin, it answers to /humanizer:humanizer. The Skills CLI version answers to /humanizer.

Run it on a draft

Paste text straight in:

/humanizer:humanizer

[paste your text here]

Or point it at a file, which is how I use it on site pages:

Humanize the prose in src/pages/services/roof-repair.md

Give it a voice to match

On its own, Humanizer makes text sound like a careful person wrote it. It doesn’t make it sound like you. Give it a sample:

/humanizer:humanizer

Here's a sample of my writing for voice matching:
[paste 2-3 paragraphs you actually wrote]

For a contractor, the best sample is usually how they text customers or explain a job on the phone. Anything they sat down to “write” tends to come out stiff.

Stack a banned-word list on top

This is the part I added. Humanizer catches patterns. I also keep a plain text file of words and phrases that never ship on my pages or my clients’ pages, plus a small script that scores a page and fails it if anything on the list shows up, including any dash used as punctuation. Humanizer does the rewrite. The script is the gate.

You don’t need a script to start. A prompt works:

Check this page against banned-words.txt. List every hit with its
line number and a plain replacement. Flag every dash used as
punctuation. Don't rewrite anything else.

“Don’t rewrite anything else” keeps Claude from quietly redoing copy you already approved.

One honest warning

It’s built for readers, not detectors. The author says so in the README: AI detectors still flag most of its output. If anyone promised you “undetectable,” this isn’t that. It can also over-correct and flatten a line that had some personality in it. Read what it changed before you accept it, the same way you’d read an edit from a person.

Design Skills That Stop Claude's Pages Looking Like AI

The three design skills I use with Claude Code (frontend-design, Impeccable, UI UX Pro Max), what each one is for, and the taste pass I run before shipping.

designskillswebsitesclaude-code Updated Sep 29, 2026
Impeccable on GitHub ↗

Ask Claude for a landing page with no guidance and you get the page everybody gets. A purple-to-blue gradient, the same default font on everything, three cards with an icon tile on top of each. It works. It also looks like every other AI-built site, and a homeowner picking a roofer reads “cheap” before they read a word.

Design skills give Claude taste rules to follow. I use three, and they do different jobs.

1. frontend-design (the baseline)

Anthropic’s own skill. Claude picks it up automatically for frontend work, and it pushes for a clear visual direction with deliberate type and color choices. It’s in Anthropic’s official plugin marketplace, so inside Claude Code:

/plugin install frontend-design@claude-plugins-official

2. Impeccable (the taste pass)

Impeccable started from frontend-design and went a lot further: one skill with 24 commands, plus 61 detector rules that catch common AI design tells without calling a model at all. Install it from your project root:

npx impeccable install

Then inside Claude Code, run /impeccable init once. It asks about the business and the audience and saves that to a PRODUCT.md file, so later commands know who the page is for.

3. UI UX Pro Max (the reference library)

A big searchable library of styles, color palettes, font pairings and UX rules, sorted by product type. I use it at the start of a build, when I want a palette and font pairing that fits a pest control company instead of a software dashboard.

/plugin marketplace add nextlevelbuilder/ui-ux-pro-max-skill
/plugin install ui-ux-pro-max@ui-ux-pro-max-skill

It needs Python 3 on your machine for its search script.

The taste pass before I ship

Once the page is built, the copy is final and the form works, I run:

/impeccable critique landing

Critique looks at hierarchy and clarity. The call button that isn’t the loudest thing on the page. The section that says the same thing as the one above it. Read what comes back and fix what’s real. Some of it will be taste you disagree with, and that’s fine.

Then the finish:

/impeccable polish landing

Polish handles spacing, alignment and consistency. I review the changes after polish the same way I’d review any code change, then check the page on my phone before it goes live.

One honest warning

These skills make pages look better. They don’t know your customer. A design pass will happily make a hero section bolder when what the page needed was a bigger phone number. Run the taste pass after the offer and the copy are right, and never let a design skill touch factual copy (prices, service areas, license numbers) without checking it yourself. Also, loading all three on the same task gives Claude conflicting opinions. Pick the one that fits the job.

Gemini as Claude Code's Second Opinion

How I plug Gemini into Claude Code with an MCP server for second opinions and heavy reading, so Claude's context stays clean for the actual build.

geminimcpresearchclaude Updated Sep 29, 2026
Gemini MCP server on GitHub ↗

Claude Code’s context window is its working memory. Every big file it reads and every long research result it pulls takes up room, and as that fills, the session gets slower and sloppier. Most of that reading didn’t need Claude in the first place.

So I hand two kinds of jobs to Gemini. Second opinions: before I commit to an approach on a build, I want a different model to poke holes in the plan. Two models trained differently miss different things. And heavy reading: long PDFs, a pile of research, a competitor’s whole site. Gemini reads it and sends back a summary, and only the summary lands in Claude’s context.

Step 1: Get a Gemini API key

Go to aistudio.google.com/apikey, sign in with a Google account and create a key. There’s a free tier to start on.

Step 2: Add a Gemini MCP server

There are a handful of Gemini MCP servers on GitHub, and some haven’t been touched in over a year. RLabs-Inc/gemini-mcp is actively maintained, MIT licensed and installs in one line:

claude mcp add gemini -s user -- env GEMINI_API_KEY=YOUR_KEY GEMINI_TOOL_PRESET=research GEMINI_ENABLED_TOOLS=brainstorm npx -y @rlabs-inc/gemini-mcp

The -s user part makes it available in every project. The two tool settings matter more than they look. By default this server loads all 37 of its tools, and every tool definition takes up room in Claude’s context, which is the exact thing you’re trying to protect. The research preset loads query, search, document and URL tools, and brainstorm adds the back-and-forth tool for second opinions.

Restart Claude Code and run /mcp to confirm gemini is connected.

Step 3: Ask for the second opinion

Before you build this, send your plan to Gemini with gemini-brainstorm.
Include the file structure and your reasoning. Bring back only the
objections you think are real and what you'd change because of them.

That last line is the point. You don’t want Gemini’s whole answer pasted into Claude’s context. You want Claude’s judgment on it.

Step 4: Hand off the heavy reading

Use gemini-summarize-pdf on each PDF in ./research/ with the
key-points style. Don't read the files yourself. Give me one combined
list of what they say about [topic], with the file name on each point.

Same idea for a long web page or a competitor’s site: let Gemini read it, let Claude act on the summary.

One honest warning

On the free tier, Google can use what you send to improve its products. Don’t send client data, contracts or anything private until you’ve turned on billing, which moves you to the paid tier where it doesn’t. The free tier is also rate limited, so a big batch of PDFs can stall halfway. This server defaults to Gemini preview models, and preview names get retired. If calls start failing on a model error, set GEMINI_PRO_MODEL to a current model name from AI Studio. And a second opinion is just that. When the two models disagree, you still make the call.

Rather have it built for you?

Everything here is free and you can run it yourself. If you'd rather hand the local SEO off to people who do it every day, that's what RankGrid is for.