Local SEO

Building a local SEO toolkit on open source software

How I added a Google Maps rank grid to an open source SEO app, what it costs per scan, and the citation, linking and reporting tools still to come.

Most local SEO software for agencies does the same handful of jobs: it checks where a business ranks on Google Maps across its area, finds its listings on other sites, crawls its website, and turns all of it into a report for the client. You pay per location, per month, for each of those.

I wanted to see how much of that I could build myself on top of an open source SEO app. This article covers what I built first, what each scan costs, what blocked me, and the three pieces I am building next. It is a progress report, so the parts that are still plans are marked as plans.

Why I started from an open source app

I did not want to write a crawler, a rank tracker and a login system from scratch. OpenSEO is an open source SEO app under the MIT licence, which means you can run it yourself, change it and rebrand it. It already has keyword research, rank tracking, a site audit, Search Console reports and backlink data.

It gets its search data from DataForSEO, a pay-as-you-go data API. That matters for cost. Instead of a monthly fee per client, you pay a fraction of a cent for each search the tool runs, and you only pay when you run something.

What it did not have was the local SEO side: a map of rankings around a business, a citation check, and a way to show any of it to a client.

The first piece: a Google Maps rank grid

A single rank check tells you where a business shows up for one searcher in one spot. On Google Maps that number changes block by block, because distance from the searcher is one of the three things Google says it uses to rank local results, along with relevance and prominence.

A rank grid runs the same search from many points around the business and puts the result on a map. You pick a keyword, the business, a grid size and the distance between points. The tool runs one Google Maps search from each point and records where the business appears in the top 20.

plumber · 5 x 5 grid · 1 km apart
20+ 14 9 12 20+ 8 5 3 6 11 5 2 1 2 7 9 3 3 4 13 20+ 15 8 16 20+
fig 1 · a 5 x 5 grid for a made-up plumber: strong at the shop, gone at the corners. Illustrative, not measured data.

A grid like this answers questions a single rank cannot. Where does the business stop showing up? Which side of town is weak? Is the problem one competitor, or a gap in the profile? Clicking any point in the tool shows the full top 20 for that spot, so you can see who is beating the business there.

What I got wrong first: the zoom level

Every Google Maps search runs at a zoom level, and the zoom changes the results. If you leave it to the data provider, some points come back with no results at all. If you fix it, the map can be too tight to include a business one grid step away.

The OpenSEO code already had a note on this from testing: at zoom 14, a business ranked third disappeared from a point one grid step to the side, and came back at zoom 12. So the grid works the zoom out from the distance between points instead, so that each search covers roughly the gap to its neighbours. Wider spacing gets a wider view.

Two smaller decisions

Paid map pins are left out of the ranking. A business that ranks first organically should not show as second because someone bought an ad above it.

The map background uses Google Maps if you add a Maps API key. Without one, the same pins show on a plain grid. The ranks come from the searches either way, so the map is optional.

What a scan costs

Each point is one Google Maps search, run through DataForSEO’s priority queue at $0.0012 per search. The cost goes up with the square of the grid size, so a 9 x 9 grid costs nine times what a 3 x 3 does.

3 x 3 grid, 9 searches$0.011
5 x 5 grid, 25 searches$0.030
7 x 7 grid, 49 searches$0.059
9 x 9 grid, 81 searches$0.097
fig 2 · data cost of one grid scan, at DataForSEO's Google Maps priority queue price of $0.0012 per search, October 2026

Even the largest grid costs less than ten US cents in data. Run a 5 x 5 grid for one keyword every week and the data comes to about $1.56 a year. You still pay for hosting, and your own time, but the per-client fee disappears.

What blocked me: verifying the DataForSEO account

The grid works on test data. My first real scan failed with an error, and the reason was not in the code. DataForSEO asks new accounts to verify before the API will run any paid search, even when the account already has trial credit on it.

The usual route is phone verification. For my account it said phone verification was not available, and the only other option was to add funds. The trial credit could not be used until I did.

If you want to try any tool built on DataForSEO, plan for that deposit before you start. Check the minimum in your own account panel first.

The second piece is about the website, not the map. OpenSEO’s site audit starts at 50 pages, which is only the default. On a copy you run yourself it allows up to 10,000 pages per crawl, or 1,000 if it has to render JavaScript.

The bigger gap is what the crawler keeps. It follows every internal link on the site, but at the end of the crawl it only stores a count per page. It does not keep which page links to which, or with what anchor text, and that is exactly what you need to plan hubs and internal links.

✕ What the crawl keeps now
/geyser-repairs · 23 internal links
/blog/burst-pipe · 9 internal links
A number per page. No way to tell what is connected to what.
✓ What the plan needs
/blog/burst-pipe → /emergency-plumber
anchor: "emergency plumber"
Every link, from and to, with its anchor text.
fig 3 · the same crawl stored two ways, for a made-up plumbing site

With the full link map saved, the tool can group pages into hubs by topic and folder, flag pages that nothing links to, count how many clicks each page sits from the homepage, and check whether each supporting page links up to its hub and back. From there it can suggest specific links, ranked by which pages get the most impressions in Search Console but rank just off page one.

That part is not built yet. I have a working mock-up of the screen, and the crawler change comes first.

Next: a citation check that does not scrape directories

The obvious way to find citations is to scrape each directory. I am not doing that. Most large directories block bots and their terms forbid it, so a scraper would break every few weeks.

The plan uses searches Google has already done the work for:

  1. Pull the business name, address and phone number from its Google Business Profile. This is the version every citation gets compared against.
  2. Run 10 to 20 Google searches through the same data API: the phone number in a few formats, the name with the town, the street address, and the name limited to each directory on a checklist.
  3. Open each result page once and read the name, address and phone number. Most directories mark these up in a standard format for search engines.
  4. Compare each one to the profile, ignoring differences that do not matter, like “St” against “Street”.
  5. Mark every listing as matching, wrong, or missing from the checklist.

Step 5 depends on the checklist, and the checklist depends on the country. Start from the ten directories in this list, not a list full of sites your customers never use.

step_01 Profile as the source Name, address and number from Google.
step_02 Search for mentions Phone, name and address queries. indexed pages only
step_03 Read each listing One visit per page found.
step_04 Compare "St" and "Street" count as the same.
step_05 Match, wrong or missing A to-do list per client.
fig 4 · the planned citation check, from profile to to-do list

This approach has two honest limits. It only finds listings Google has indexed, which covers the ones that matter for rankings but not every page that exists. And it finds problems without fixing them. Updating the listings is still manual, or done through a paid service that pushes changes to directories for you.

The plan is a private link per client that shows their own live data: the Maps grid, their keyword positions, clicks from Search Console, and a short written plan for the month. Nothing on it is copied by hand, so it is always current. The written part, what we are doing this month and why, is the only bit a person writes.

This is also a mock-up for now.

Where each piece stands

Job Paid tools that do it What I am using Status
Rank grid on Google Maps Local Falcon, BrightLocal Built into OpenSEO, data from DataForSEO Built, tested on sample data
Full site crawl Screaming Frog, Sitebulb OpenSEO site audit, up to 10,000 pages Works today
Internal link map and suggestions Sitebulb, Link Whisper Crawler change plus a new screen Mock-up
Citation check BrightLocal, Whitespark Google searches through DataForSEO Planned
Live client report AgencyAnalytics One private link per client Mock-up

The rank grid is the piece to copy first if you are building something similar. It is the most useful view for a local business and costs cents to run.

FAQ

What is a geo grid in local SEO?

It is a set of points spread evenly around a business. The same Google Maps search runs from each point, and the grid shows where the business ranks at each one, so you can see how far its visibility reaches.

How much does a geo grid scan cost?

Through DataForSEO’s priority queue, each point costs $0.0012, so a 5 x 5 grid is about three US cents and a 9 x 9 grid is under ten. Paid tools charge a monthly fee that includes their own markup and features on top of this.

Can I check local rankings for free?

You can search on your own phone, but you only see the results for where you are standing. To see rankings across an area you need searches run from other locations, which means a paid data source or a tool built on one.

Do I need a Google Maps API key for a rank grid?

Not for the rankings. The searches come from the data provider. A Maps key only adds the map background behind the pins.

Start with the grid

If you only build one piece, build the rank grid. Run a 3 x 3 grid for your main keyword, look at where the business drops off, and let that decide what to work on first.

Portrait of Liam Fraser
// written byLiam FraserSEO specialist with 3 years of experience. Liam writes about what works in local, technical and AI search.About SerpSurfers →