antigravity-seo-kit 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/agent.md +96 -0
- package/.agent/skills/seo/SKILL.md +153 -0
- package/.agent/skills/seo/references/cwv-thresholds.md +108 -0
- package/.agent/skills/seo/references/eeat-framework.md +214 -0
- package/.agent/skills/seo/references/local-schema-types.md +230 -0
- package/.agent/skills/seo/references/local-seo-signals.md +218 -0
- package/.agent/skills/seo/references/maps-api-endpoints.md +160 -0
- package/.agent/skills/seo/references/maps-free-apis.md +176 -0
- package/.agent/skills/seo/references/maps-gbp-checklist.md +150 -0
- package/.agent/skills/seo/references/maps-geo-grid.md +154 -0
- package/.agent/skills/seo/references/quality-gates.md +155 -0
- package/.agent/skills/seo/references/schema-types.md +118 -0
- package/.agent/skills/seo/schema/templates.json +213 -0
- package/.agent/skills/seo/scripts/analyze_visual.py +217 -0
- package/.agent/skills/seo/scripts/capture_screenshot.py +181 -0
- package/.agent/skills/seo/scripts/fetch_page.py +196 -0
- package/.agent/skills/seo/scripts/parse_html.py +201 -0
- package/.agent/skills/seo-audit/SKILL.md +278 -0
- package/.agent/skills/seo-competitor-pages/SKILL.md +212 -0
- package/.agent/skills/seo-content/SKILL.md +230 -0
- package/.agent/skills/seo-dataforseo/SKILL.md +418 -0
- package/.agent/skills/seo-geo/SKILL.md +305 -0
- package/.agent/skills/seo-google/SKILL.md +405 -0
- package/.agent/skills/seo-google/assets/templates/cwv-audit-report.md +48 -0
- package/.agent/skills/seo-google/assets/templates/gsc-performance-report.md +44 -0
- package/.agent/skills/seo-google/assets/templates/indexation-status-report.md +43 -0
- package/.agent/skills/seo-google/references/auth-setup.md +154 -0
- package/.agent/skills/seo-google/references/ga4-data-api.md +184 -0
- package/.agent/skills/seo-google/references/indexing-api.md +107 -0
- package/.agent/skills/seo-google/references/keyword-planner-api.md +66 -0
- package/.agent/skills/seo-google/references/nlp-api.md +55 -0
- package/.agent/skills/seo-google/references/pagespeed-crux-api.md +204 -0
- package/.agent/skills/seo-google/references/rate-limits-quotas.md +75 -0
- package/.agent/skills/seo-google/references/search-console-api.md +156 -0
- package/.agent/skills/seo-google/references/supplementary-apis.md +99 -0
- package/.agent/skills/seo-google/references/youtube-api.md +49 -0
- package/.agent/skills/seo-google/scripts/crux_history.py +321 -0
- package/.agent/skills/seo-google/scripts/ga4_report.py +478 -0
- package/.agent/skills/seo-google/scripts/google_auth.py +795 -0
- package/.agent/skills/seo-google/scripts/google_report.py +2273 -0
- package/.agent/skills/seo-google/scripts/gsc_inspect.py +340 -0
- package/.agent/skills/seo-google/scripts/gsc_query.py +378 -0
- package/.agent/skills/seo-google/scripts/indexing_notify.py +313 -0
- package/.agent/skills/seo-google/scripts/keyword_planner.py +297 -0
- package/.agent/skills/seo-google/scripts/nlp_analyze.py +309 -0
- package/.agent/skills/seo-google/scripts/pagespeed_check.py +649 -0
- package/.agent/skills/seo-google/scripts/youtube_search.py +355 -0
- package/.agent/skills/seo-hreflang/SKILL.md +192 -0
- package/.agent/skills/seo-image-gen/SKILL.md +211 -0
- package/.agent/skills/seo-image-gen/references/cost-tracking.md +47 -0
- package/.agent/skills/seo-image-gen/references/gemini-models.md +200 -0
- package/.agent/skills/seo-image-gen/references/mcp-tools.md +115 -0
- package/.agent/skills/seo-image-gen/references/post-processing.md +192 -0
- package/.agent/skills/seo-image-gen/references/presets.md +69 -0
- package/.agent/skills/seo-image-gen/references/prompt-engineering.md +411 -0
- package/.agent/skills/seo-image-gen/references/seo-image-presets.md +137 -0
- package/.agent/skills/seo-image-gen/scripts/batch.py +97 -0
- package/.agent/skills/seo-image-gen/scripts/cost_tracker.py +191 -0
- package/.agent/skills/seo-image-gen/scripts/edit.py +141 -0
- package/.agent/skills/seo-image-gen/scripts/generate.py +149 -0
- package/.agent/skills/seo-image-gen/scripts/presets.py +153 -0
- package/.agent/skills/seo-image-gen/scripts/setup_mcp.py +151 -0
- package/.agent/skills/seo-image-gen/scripts/validate_setup.py +133 -0
- package/.agent/skills/seo-images/SKILL.md +176 -0
- package/.agent/skills/seo-local/SKILL.md +381 -0
- package/.agent/skills/seo-maps/SKILL.md +328 -0
- package/.agent/skills/seo-page/SKILL.md +86 -0
- package/.agent/skills/seo-plan/SKILL.md +118 -0
- package/.agent/skills/seo-plan/assets/agency.md +175 -0
- package/.agent/skills/seo-plan/assets/ecommerce.md +167 -0
- package/.agent/skills/seo-plan/assets/generic.md +144 -0
- package/.agent/skills/seo-plan/assets/local-service.md +160 -0
- package/.agent/skills/seo-plan/assets/publisher.md +153 -0
- package/.agent/skills/seo-plan/assets/saas.md +135 -0
- package/.agent/skills/seo-programmatic/SKILL.md +171 -0
- package/.agent/skills/seo-schema/SKILL.md +223 -0
- package/.agent/skills/seo-sitemap/SKILL.md +180 -0
- package/.agent/skills/seo-technical/SKILL.md +211 -0
- package/.agent/workflows/seo-audit.md +17 -0
- package/.agent/workflows/seo-competitor-pages.md +12 -0
- package/.agent/workflows/seo-content.md +14 -0
- package/.agent/workflows/seo-geo.md +12 -0
- package/.agent/workflows/seo-google.md +12 -0
- package/.agent/workflows/seo-hreflang.md +12 -0
- package/.agent/workflows/seo-images.md +13 -0
- package/.agent/workflows/seo-local.md +12 -0
- package/.agent/workflows/seo-maps.md +11 -0
- package/.agent/workflows/seo-page.md +13 -0
- package/.agent/workflows/seo-plan.md +13 -0
- package/.agent/workflows/seo-programmatic.md +12 -0
- package/.agent/workflows/seo-schema.md +11 -0
- package/.agent/workflows/seo-sitemap.md +9 -0
- package/.agent/workflows/seo-technical.md +18 -0
- package/LICENSE +88 -0
- package/README.md +122 -0
- package/bin/cli.js +117 -0
- package/docs/ARCHITECTURE.md +218 -0
- package/docs/COMMANDS.md +184 -0
- package/docs/INSTALLATION.md +100 -0
- package/docs/MCP-INTEGRATION.md +153 -0
- package/docs/TROUBLESHOOTING.md +151 -0
- package/docs/superpowers/plans/2026-03-13-github-audit-fixes.md +511 -0
- package/extensions/banana/README.md +95 -0
- package/extensions/banana/docs/BANANA-SETUP.md +86 -0
- package/extensions/banana/install.sh +170 -0
- package/extensions/banana/references/cost-tracking.md +47 -0
- package/extensions/banana/references/gemini-models.md +200 -0
- package/extensions/banana/references/mcp-tools.md +115 -0
- package/extensions/banana/references/post-processing.md +192 -0
- package/extensions/banana/references/presets.md +69 -0
- package/extensions/banana/references/prompt-engineering.md +411 -0
- package/extensions/banana/references/seo-image-presets.md +137 -0
- package/extensions/banana/scripts/batch.py +97 -0
- package/extensions/banana/scripts/cost_tracker.py +191 -0
- package/extensions/banana/scripts/edit.py +141 -0
- package/extensions/banana/scripts/generate.py +149 -0
- package/extensions/banana/scripts/presets.py +153 -0
- package/extensions/banana/scripts/setup_mcp.py +151 -0
- package/extensions/banana/scripts/validate_setup.py +133 -0
- package/extensions/banana/uninstall.sh +43 -0
- package/extensions/dataforseo/README.md +169 -0
- package/extensions/dataforseo/docs/DATAFORSEO-SETUP.md +74 -0
- package/extensions/dataforseo/field-config.json +280 -0
- package/extensions/dataforseo/install.ps1 +110 -0
- package/extensions/dataforseo/install.sh +161 -0
- package/extensions/dataforseo/uninstall.ps1 +35 -0
- package/extensions/dataforseo/uninstall.sh +39 -0
- package/lib/api.js +190 -0
- package/lib/fingerprint.js +68 -0
- package/lib/installer.js +486 -0
- package/lib/utils.js +254 -0
- package/package.json +40 -0
- package/pyproject.toml +11 -0
- package/requirements-google.txt +15 -0
- package/requirements.txt +11 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<!-- Updated: 2026-03-23 -->
|
|
2
|
+
# Free Maps APIs for claude-seo
|
|
3
|
+
|
|
4
|
+
## Source Key
|
|
5
|
+
|
|
6
|
+
- **Docs**: Official API documentation for each service
|
|
7
|
+
- **Policy**: Official usage policies and terms
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Overpass API (Best Free Option for Competitor Discovery)
|
|
12
|
+
|
|
13
|
+
**Base URL:** `https://overpass-api.de/api/interpreter`
|
|
14
|
+
**Docs:** https://wiki.openstreetmap.org/wiki/Overpass_API
|
|
15
|
+
**License:** ODbL (attribution required: "Data from OpenStreetMap")
|
|
16
|
+
|
|
17
|
+
### Rate Limits
|
|
18
|
+
|
|
19
|
+
- Slot-based: ~2 concurrent queries per IP
|
|
20
|
+
- Guideline: ~10,000 requests/day, ~1 GB/day download
|
|
21
|
+
- Default timeout: 180 seconds, 512 MiB memory per query
|
|
22
|
+
- Use `[timeout:25]` for lighter queries
|
|
23
|
+
|
|
24
|
+
### Query Templates
|
|
25
|
+
|
|
26
|
+
**Restaurants within 5km radius:**
|
|
27
|
+
```bash
|
|
28
|
+
curl -s "https://overpass-api.de/api/interpreter" \
|
|
29
|
+
--data-urlencode 'data=[out:json][timeout:25];(node["amenity"="restaurant"](around:5000,LAT,LNG);way["amenity"="restaurant"](around:5000,LAT,LNG););out body;>;out skel qt;'
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**All businesses on a street:**
|
|
33
|
+
```bash
|
|
34
|
+
curl -s "https://overpass-api.de/api/interpreter" \
|
|
35
|
+
--data-urlencode 'data=[out:json][timeout:25];way["name"="STREET_NAME"]["addr:city"="CITY"];(._;>;);out body;'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Competitor POIs by category in bounding box:**
|
|
39
|
+
```bash
|
|
40
|
+
curl -s "https://overpass-api.de/api/interpreter" \
|
|
41
|
+
--data-urlencode 'data=[out:json][timeout:25];(node["amenity"="dentist"](SOUTH,WEST,NORTH,EAST);way["amenity"="dentist"](SOUTH,WEST,NORTH,EAST););out body;>;out skel qt;'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Key OSM Tags for Local SEO
|
|
45
|
+
|
|
46
|
+
| Category | OSM Tag | Examples |
|
|
47
|
+
|----------|---------|---------|
|
|
48
|
+
| Food & Drink | `amenity=restaurant`, `amenity=cafe`, `amenity=fast_food` | Restaurants, cafes, takeaway |
|
|
49
|
+
| Healthcare | `amenity=dentist`, `amenity=doctors`, `amenity=pharmacy` | Dental, medical, pharmacy |
|
|
50
|
+
| Legal | `office=lawyer`, `office=notary` | Law firms, notaries |
|
|
51
|
+
| Home Services | `craft=plumber`, `craft=electrician`, `craft=hvac` | Trades, contractors |
|
|
52
|
+
| Retail | `shop=supermarket`, `shop=clothes`, `shop=car` | All retail types |
|
|
53
|
+
| Automotive | `shop=car`, `shop=car_repair`, `amenity=fuel` | Dealers, repair, gas |
|
|
54
|
+
| Hospitality | `tourism=hotel`, `tourism=motel`, `tourism=guest_house` | Accommodation |
|
|
55
|
+
| Financial | `amenity=bank`, `office=insurance`, `office=accountant` | Banks, insurance, accounting |
|
|
56
|
+
|
|
57
|
+
### Response Fields
|
|
58
|
+
|
|
59
|
+
Each element returns: `id`, `lat`, `lon`, `tags` object containing `name`, `phone`, `website`, `opening_hours`, `addr:street`, `addr:housenumber`, `addr:city`, `addr:postcode`, `cuisine`, `brand`, etc.
|
|
60
|
+
|
|
61
|
+
### Limitations
|
|
62
|
+
|
|
63
|
+
- No reviews, ratings, or popularity data
|
|
64
|
+
- No GBP-specific information
|
|
65
|
+
- Data quality varies by region (excellent in Europe, inconsistent elsewhere)
|
|
66
|
+
- Volunteer-contributed data; may be outdated
|
|
67
|
+
- Interactive tester: https://overpass-turbo.eu/
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Geoapify Places API (Structured POI Search)
|
|
72
|
+
|
|
73
|
+
**Base URL:** `https://api.geoapify.com/v2/places`
|
|
74
|
+
**Docs:** https://apidocs.geoapify.com/docs/places/
|
|
75
|
+
**Pricing:** https://www.geoapify.com/pricing
|
|
76
|
+
|
|
77
|
+
### Free Tier
|
|
78
|
+
|
|
79
|
+
- **3,000 credits/day** (1 credit = 20 places returned)
|
|
80
|
+
- 5 requests/second
|
|
81
|
+
- Requires API key (free registration, no credit card)
|
|
82
|
+
- **Caching and storage explicitly permitted** (unlike Google)
|
|
83
|
+
|
|
84
|
+
### Query Template
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
curl -s "https://api.geoapify.com/v2/places?categories=catering.restaurant&filter=circle:LNG,LAT,5000&limit=20&apiKey=YOUR_KEY"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Category Hierarchy
|
|
91
|
+
|
|
92
|
+
Uses dot-separated categories: `catering.restaurant`, `commercial.supermarket`, `healthcare.dentist`, `service.financial.accounting`, `commercial.vehicle.car_dealer`
|
|
93
|
+
|
|
94
|
+
### Response Format
|
|
95
|
+
|
|
96
|
+
GeoJSON FeatureCollection. Each feature has `properties`: `name`, `city`, `state`, `postcode`, `country`, `street`, `housenumber`, `phone`, `website`, `categories`, `lat`, `lon`, `place_id`, `formatted` (full address string)
|
|
97
|
+
|
|
98
|
+
### Advantages Over Raw Overpass
|
|
99
|
+
|
|
100
|
+
- Cleaner, structured responses
|
|
101
|
+
- Aggregated data (OSM + OpenAddresses + WhosOnFirst + GeoNames)
|
|
102
|
+
- Hierarchical category taxonomy
|
|
103
|
+
- No rate limit surprises (clear credit system)
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Nominatim (Geocoding Only)
|
|
108
|
+
|
|
109
|
+
**Base URL:** `https://nominatim.openstreetmap.org`
|
|
110
|
+
**Docs:** https://nominatim.org/release-docs/latest/api/Overview/
|
|
111
|
+
**Policy:** https://operations.osmfoundation.org/policies/nominatim/
|
|
112
|
+
|
|
113
|
+
### Rate Limits (STRICT)
|
|
114
|
+
|
|
115
|
+
- **1 request/second** (absolute)
|
|
116
|
+
- Must include valid `User-Agent` header (stock library agents rejected)
|
|
117
|
+
- Auto-complete queries **forbidden**
|
|
118
|
+
- Bulk geocoding **forbidden** on public instance
|
|
119
|
+
- Repeated identical queries trigger bans (cache results)
|
|
120
|
+
|
|
121
|
+
### Forward Geocoding
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
curl -s "https://nominatim.openstreetmap.org/search?q=123+Main+St+Austin+TX&format=json&addressdetails=1" \
|
|
125
|
+
-H "User-Agent: claude-seo/1.7.0"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Reverse Geocoding
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
curl -s "https://nominatim.openstreetmap.org/reverse?lat=40.7128&lon=-74.0060&format=json" \
|
|
132
|
+
-H "User-Agent: claude-seo/1.7.0"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Response Fields
|
|
136
|
+
|
|
137
|
+
`place_id`, `lat`, `lon`, `display_name`, `importance`, `category`, `type`, `address` object (house_number, road, city, state, postcode, country)
|
|
138
|
+
|
|
139
|
+
### Best Use
|
|
140
|
+
|
|
141
|
+
- Address-to-coordinates conversion for geo-grid center point
|
|
142
|
+
- Reverse geocoding to validate business addresses
|
|
143
|
+
- **NOT suitable** for business listing discovery (use Overpass or Geoapify)
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Rate Limit Enforcement Pattern
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Nominatim: enforce 1 req/sec with sleep
|
|
151
|
+
for addr in "${addresses[@]}"; do
|
|
152
|
+
curl -s "https://nominatim.openstreetmap.org/search?q=${addr}&format=json" \
|
|
153
|
+
-H "User-Agent: claude-seo/1.7.0"
|
|
154
|
+
sleep 1.1
|
|
155
|
+
done
|
|
156
|
+
|
|
157
|
+
# Overpass: no explicit rate limit, but use reasonable timeouts
|
|
158
|
+
# If HTTP 429 returned, implement exponential backoff
|
|
159
|
+
|
|
160
|
+
# Geoapify: 5 req/sec on free tier, no explicit enforcement needed
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Comparison Table
|
|
166
|
+
|
|
167
|
+
| Feature | Overpass | Geoapify | Nominatim |
|
|
168
|
+
|---------|---------|----------|-----------|
|
|
169
|
+
| Business discovery | Yes (tags) | Yes (categories) | Limited |
|
|
170
|
+
| Reviews/ratings | No | No | No |
|
|
171
|
+
| Geocoding | No | Yes | **Best** |
|
|
172
|
+
| Rate limit | ~10k/day | 3k credits/day | 1 req/sec |
|
|
173
|
+
| Auth required | No | API key | No |
|
|
174
|
+
| Caching allowed | Yes | **Explicitly** | **Required** |
|
|
175
|
+
| Data quality | Regional | Aggregated | Regional |
|
|
176
|
+
| Best for | Radius competitor search | Structured POI search | Address resolution |
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<!-- Updated: 2026-03-23 -->
|
|
2
|
+
# GBP Profile Completeness Checklist (Via API)
|
|
3
|
+
|
|
4
|
+
This checklist scores a Google Business Profile using data retrieved from
|
|
5
|
+
the DataForSEO My Business Info API. It measures profile completeness on
|
|
6
|
+
the maps PLATFORM, not on-page signals (seo-local handles on-page).
|
|
7
|
+
|
|
8
|
+
## Sources
|
|
9
|
+
|
|
10
|
+
- Google official: https://support.google.com/business/answer/7091
|
|
11
|
+
- Whitespark 2026 Local Search Ranking Factors (Study)
|
|
12
|
+
- BrightLocal LCRS 2026 (Study)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Scoring System
|
|
17
|
+
|
|
18
|
+
Each field: **Present + Optimized = 2pts**, **Present = 1pt**, **Missing = 0pts**
|
|
19
|
+
|
|
20
|
+
Total possible: 50 points. Normalize to 0-100 scale: `(score / 50) * 100`
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Critical Fields (Direct Ranking Impact)
|
|
25
|
+
|
|
26
|
+
| # | Field | Points | Optimized Criteria |
|
|
27
|
+
|---|-------|--------|-------------------|
|
|
28
|
+
| 1 | **Primary category** | 2 | Most specific subtype for industry (e.g., "Cosmetic Dentist" not "Dentist") |
|
|
29
|
+
| 2 | **Additional categories** | 2 | 3-5 relevant categories (optimal: 4 additional per BrightLocal) |
|
|
30
|
+
| 3 | **Business name** | 2 | Matches real-world name exactly (no keyword stuffing) |
|
|
31
|
+
| 4 | **Physical address** | 2 | Complete, matches website NAP |
|
|
32
|
+
| 5 | **Phone number** | 2 | Local number (not toll-free), matches website |
|
|
33
|
+
| 6 | **Website URL** | 2 | Points to correct page (not strongest page -- Diversity Update risk) |
|
|
34
|
+
| 7 | **Business hours** | 2 | Complete with special/holiday hours. Open-at-search-time = factor #5 |
|
|
35
|
+
| 8 | **Verified status** | 2 | Google Verified badge active |
|
|
36
|
+
|
|
37
|
+
**Subtotal: 16 points (8 fields)**
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Important Fields (Significant Influence)
|
|
42
|
+
|
|
43
|
+
| # | Field | Points | Optimized Criteria |
|
|
44
|
+
|---|-------|--------|-------------------|
|
|
45
|
+
| 9 | **Business description** | 2 | 250-750 chars, includes primary service + location keywords naturally |
|
|
46
|
+
| 10 | **Services list** | 2 | All core services listed with descriptions |
|
|
47
|
+
| 11 | **Products** | 2 | Key products/services with prices (if applicable) |
|
|
48
|
+
| 12 | **Photos** | 2 | 10+ photos across types: logo, cover, interior, exterior, team, products |
|
|
49
|
+
| 13 | **Photo recency** | 2 | Photos uploaded within last 30 days |
|
|
50
|
+
| 14 | **Attributes** | 2 | Relevant attributes set (accessibility, payments, amenities, identity) |
|
|
51
|
+
| 15 | **Service areas** | 2 | Defined for SABs, up to 20 areas (cities or zip codes) |
|
|
52
|
+
| 16 | **Menu/services link** | 2 | Menu URL (restaurants) or services URL (others) |
|
|
53
|
+
|
|
54
|
+
**Subtotal: 16 points (8 fields)**
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Supplementary Fields (Supporting Signals)
|
|
59
|
+
|
|
60
|
+
| # | Field | Points | Optimized Criteria |
|
|
61
|
+
|---|-------|--------|-------------------|
|
|
62
|
+
| 17 | **Google Posts** | 2 | Active posting (1+/week). Types: update, offer, event, product |
|
|
63
|
+
| 18 | **Post recency** | 2 | Post within last 7 days |
|
|
64
|
+
| 19 | **Booking link** | 2 | Appointment/reservation URL configured |
|
|
65
|
+
| 20 | **Social profiles** | 2 | Linked via `sameAs` or GBP social links |
|
|
66
|
+
| 21 | **Logo** | 2 | High-quality square logo uploaded |
|
|
67
|
+
| 22 | **Cover photo** | 2 | On-brand, high-resolution cover image |
|
|
68
|
+
| 23 | **Videos** | 2 | At least 1 video uploaded |
|
|
69
|
+
| 24 | **Owner responses** | 2 | Responding to reviews (target: 80%+ response rate) |
|
|
70
|
+
| 25 | **Q&A engagement** | 2 | FAQ content on website (GBP Q&A deprecated Dec 2025) |
|
|
71
|
+
|
|
72
|
+
**Subtotal: 18 points (9 fields)**
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Industry-Specific Weight Adjustments
|
|
77
|
+
|
|
78
|
+
When scoring, apply multipliers to fields that matter more for specific industries:
|
|
79
|
+
|
|
80
|
+
### Restaurant
|
|
81
|
+
- Menu/services link: **x2** (critical for food-related searches)
|
|
82
|
+
- Photos: **x1.5** (food photos drive engagement)
|
|
83
|
+
- Booking link: **x1.5** (reservation systems expected)
|
|
84
|
+
- Attributes: **x1.5** (dietary, dine-in/takeout/delivery critical)
|
|
85
|
+
|
|
86
|
+
### Healthcare
|
|
87
|
+
- Business hours: **x1.5** (patients need accurate hours)
|
|
88
|
+
- Attributes: **x1.5** (insurance, accessibility, telehealth)
|
|
89
|
+
- Services list: **x2** (insurance and procedure matching)
|
|
90
|
+
|
|
91
|
+
### Legal
|
|
92
|
+
- Business description: **x1.5** (practice area clarity)
|
|
93
|
+
- Services list: **x2** (practice area matching drives visibility)
|
|
94
|
+
- Photos: **x0.5** (less impactful for legal)
|
|
95
|
+
|
|
96
|
+
### Home Services
|
|
97
|
+
- Service areas: **x2** (SAB model depends on this)
|
|
98
|
+
- Business hours: **x1.5** (emergency availability)
|
|
99
|
+
- Photos: **x1.5** (before/after project photos)
|
|
100
|
+
|
|
101
|
+
### Real Estate
|
|
102
|
+
- Photos: **x2** (property photos critical)
|
|
103
|
+
- Social profiles: **x1.5** (agent branding)
|
|
104
|
+
- Posts: **x1.5** (listing updates)
|
|
105
|
+
|
|
106
|
+
### Automotive
|
|
107
|
+
- Products: **x2** (vehicle inventory)
|
|
108
|
+
- Photos: **x2** (vehicle photos)
|
|
109
|
+
- Services list: **x1.5** (sales + service departments)
|
|
110
|
+
|
|
111
|
+
### Re-normalization After Multipliers
|
|
112
|
+
|
|
113
|
+
After applying industry multipliers, re-normalize so the total remains 0-100:
|
|
114
|
+
```
|
|
115
|
+
final_score = (weighted_raw_score / max_possible_weighted_score) * 100
|
|
116
|
+
```
|
|
117
|
+
This ensures consistent scoring regardless of which industry multipliers are active.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Score Interpretation
|
|
122
|
+
|
|
123
|
+
| Score | Rating | Action |
|
|
124
|
+
|-------|--------|--------|
|
|
125
|
+
| 90-100 | Excellent | Maintain posting cadence and photo freshness |
|
|
126
|
+
| 75-89 | Good | Fill remaining gaps in supplementary fields |
|
|
127
|
+
| 50-74 | Needs Work | Missing important fields, address Critical + Important gaps |
|
|
128
|
+
| 25-49 | Poor | Major profile gaps hurting visibility. Prioritize Critical fields |
|
|
129
|
+
| 0-24 | Critical | Profile barely exists or unclaimed. Start with verification + Critical fields |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Data Mapping (DataForSEO → Checklist)
|
|
134
|
+
|
|
135
|
+
| Checklist Field | DataForSEO My Business Info Field |
|
|
136
|
+
|----------------|----------------------------------|
|
|
137
|
+
| Primary category | `category` |
|
|
138
|
+
| Additional categories | `additional_categories` |
|
|
139
|
+
| Business name | `title` |
|
|
140
|
+
| Address | `address_info` |
|
|
141
|
+
| Phone | `contact_info` (type: phone) |
|
|
142
|
+
| Website | `domain`, `url` |
|
|
143
|
+
| Hours | `work_hours` |
|
|
144
|
+
| Description | `description` |
|
|
145
|
+
| Services | (separate API or attributes) |
|
|
146
|
+
| Photos | `photos_count`, `main_image` |
|
|
147
|
+
| Attributes | `attributes` (grouped by type) |
|
|
148
|
+
| Popular times | `popular_times` |
|
|
149
|
+
| Posts | My Business Updates API |
|
|
150
|
+
| Verified status | Not directly exposed — infer from profile completeness + Maps SERP presence, or flag as "Unknown (manual check required)" |
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<!-- Updated: 2026-03-23 -->
|
|
2
|
+
# Geo-Grid Rank Tracking Algorithm
|
|
3
|
+
|
|
4
|
+
## Concept
|
|
5
|
+
|
|
6
|
+
Geo-grid rank tracking simulates Google Maps searches from multiple GPS
|
|
7
|
+
coordinates around a business to show how rankings vary across a geographic
|
|
8
|
+
area. The output is a heatmap revealing where the business ranks well (green)
|
|
9
|
+
and where competitors dominate (red).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Grid Generation (Haversine-Based)
|
|
14
|
+
|
|
15
|
+
### Algorithm
|
|
16
|
+
|
|
17
|
+
1. Take center coordinates (business location): `center_lat`, `center_lng`
|
|
18
|
+
2. Define grid size (e.g., 7x7 = 49 points) and radius in km
|
|
19
|
+
3. Calculate spacing: `step = (2 * radius_km) / (grid_size - 1)`
|
|
20
|
+
4. Generate grid points using offset formula:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
For each row i (0 to grid_size-1) and column j (0 to grid_size-1):
|
|
24
|
+
dy = (i - center_index) * step_km
|
|
25
|
+
dx = (j - center_index) * step_km
|
|
26
|
+
new_lat = center_lat + (dy / 111.32)
|
|
27
|
+
new_lng = center_lng + (dx / (111.32 * cos(center_lat * pi/180)))
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Where `center_index = (grid_size - 1) / 2` and `111.32 km = 1 degree latitude`.
|
|
31
|
+
|
|
32
|
+
### Grid Sizes and Use Cases
|
|
33
|
+
|
|
34
|
+
| Grid | Points | Typical Radius | Best For | Est. Cost (Live) |
|
|
35
|
+
|------|--------|---------------|----------|-----------------|
|
|
36
|
+
| 3x3 | 9 | 2 km | Quick snapshot, low budget | $0.018/keyword |
|
|
37
|
+
| 5x5 | 25 | 3 km | Standard urban audit | $0.050/keyword |
|
|
38
|
+
| **7x7** | **49** | **5 km** | **Default. Best balance of coverage and cost** | **$0.098/keyword** |
|
|
39
|
+
| 9x9 | 81 | 8 km | Suburban/wide service area | $0.162/keyword |
|
|
40
|
+
| 13x13 | 169 | 15 km | Rural or large metro | $0.338/keyword |
|
|
41
|
+
|
|
42
|
+
**Radius guidelines:** Urban dense = 2-5 km, suburban = 5-10 km, rural = 10-25 km.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## DataForSEO Integration
|
|
47
|
+
|
|
48
|
+
Use the Google Maps SERP API with `location_coordinate` parameter:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"keyword": "dentist",
|
|
53
|
+
"location_coordinate": "30.2672,-97.7431,15z",
|
|
54
|
+
"language_code": "en",
|
|
55
|
+
"device": "mobile",
|
|
56
|
+
"depth": 20
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
For each grid point, fire one API call with the point's lat/lng. Parse the
|
|
61
|
+
`items` array to find the target business rank (position in results).
|
|
62
|
+
|
|
63
|
+
**Rate optimization:** DataForSEO allows up to 100 tasks per POST. For a 7x7
|
|
64
|
+
grid, batch all 49 tasks into a single request to minimize HTTP overhead.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Share of Local Voice (SoLV)
|
|
69
|
+
|
|
70
|
+
Metric pioneered by Local Falcon. Measures visibility across the grid.
|
|
71
|
+
|
|
72
|
+
### Calculation
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
SoLV = (points_in_top_3 / total_grid_points) * 100
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Interpretation
|
|
79
|
+
|
|
80
|
+
| SoLV | Interpretation |
|
|
81
|
+
|------|---------------|
|
|
82
|
+
| 80-100% | Dominant. Business owns the local area. |
|
|
83
|
+
| 60-79% | Strong. Visible in most of the service area. |
|
|
84
|
+
| 40-59% | Moderate. Significant gaps in coverage. |
|
|
85
|
+
| 20-39% | Weak. Competitors dominate most areas. |
|
|
86
|
+
| 0-19% | Critical. Nearly invisible in maps results. |
|
|
87
|
+
|
|
88
|
+
### Extended Metrics
|
|
89
|
+
|
|
90
|
+
- **Average Rank**: Mean position across all grid points (lower = better)
|
|
91
|
+
- **Visibility Score**: Weighted average where top 3 = 3pts, 4-10 = 1pt, 10+ = 0pts
|
|
92
|
+
- **Worst Quadrant**: Identify which compass direction has weakest rankings
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## ASCII Heatmap Rendering
|
|
97
|
+
|
|
98
|
+
For terminal/Markdown output, render a grid using rank-position symbols:
|
|
99
|
+
|
|
100
|
+
### Format
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
Geo-Grid: "dentist" (7x7, 5km radius, center: 30.267, -97.743)
|
|
104
|
+
|
|
105
|
+
W -------- E
|
|
106
|
+
N 1 1 2 3 5 8 -
|
|
107
|
+
| 1 1 1 2 3 6 9
|
|
108
|
+
| 2 1 [1] 1 2 4 7
|
|
109
|
+
| 3 2 1 1 1 3 5
|
|
110
|
+
| 5 3 2 1 2 4 8
|
|
111
|
+
| 8 5 3 2 3 6 -
|
|
112
|
+
S - 8 5 4 5 9 -
|
|
113
|
+
|
|
114
|
+
Legend: [1]=center, 1-3=top 3 (strong), 4-10=visible, -=not ranked
|
|
115
|
+
SoLV: 57% (28/49 grid points in top 3)
|
|
116
|
+
Avg Rank: 3.4 | Weakest: NE quadrant (avg rank 7.2)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Color Mapping (for enhanced output)
|
|
120
|
+
|
|
121
|
+
| Position | Symbol | Meaning |
|
|
122
|
+
|----------|--------|---------|
|
|
123
|
+
| 1 | `1` | #1 ranking (best) |
|
|
124
|
+
| 2-3 | `2`, `3` | Top 3 (strong local presence) |
|
|
125
|
+
| 4-10 | `4`-`9` | Visible but not dominant |
|
|
126
|
+
| 11-20 | `+` | Buried in results |
|
|
127
|
+
| Not found | `-` | Not ranking at this point |
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Multi-Keyword Grid
|
|
132
|
+
|
|
133
|
+
For comprehensive analysis, scan 2-3 keywords on the same grid:
|
|
134
|
+
|
|
135
|
+
1. Primary service keyword (e.g., "dentist")
|
|
136
|
+
2. Brand + location (e.g., "Smith Dental Austin")
|
|
137
|
+
3. Long-tail intent (e.g., "emergency dentist near me")
|
|
138
|
+
|
|
139
|
+
**Cost for 3-keyword 7x7 scan:** 147 API calls = ~$0.29 (live) or ~$0.088 (standard)
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Cost Warning Template
|
|
144
|
+
|
|
145
|
+
Before running a geo-grid scan, display:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
Geo-Grid Scan Estimate:
|
|
149
|
+
Grid: 7x7 (49 points)
|
|
150
|
+
Keywords: 3
|
|
151
|
+
API calls: 147
|
|
152
|
+
Estimated cost: $0.09 (standard) - $0.29 (live)
|
|
153
|
+
Proceed? [DataForSEO credits will be consumed]
|
|
154
|
+
```
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Content Quality Gates
|
|
2
|
+
|
|
3
|
+
## Minimum Word Counts by Page Type
|
|
4
|
+
|
|
5
|
+
| Page Type | Min Words | Unique Content % | Notes |
|
|
6
|
+
|-----------|-----------|-----------------|-------|
|
|
7
|
+
| Homepage | 500 | 100% | Must clearly communicate value proposition |
|
|
8
|
+
| Service / Feature Page | 800 | 100% | Detailed explanation of offering |
|
|
9
|
+
| Location (Primary) | 600 | 60%+ | City headquarters or main service area |
|
|
10
|
+
| Location (Secondary) | 500 | 40%+ | Satellite locations |
|
|
11
|
+
| Blog Post | 1,500 | 100% | In-depth, valuable content |
|
|
12
|
+
| Product Page | 400 | 80%+ | Unique descriptions, specs |
|
|
13
|
+
| Category Page | 400 | 100% | Unique intro, not just product listings |
|
|
14
|
+
| About Page | 400 | 100% | Company story, team, values |
|
|
15
|
+
| Landing Page | 600 | 100% | Focused conversion content |
|
|
16
|
+
| FAQ Page | 800 | 100% | Comprehensive Q&A |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Location Page Thresholds
|
|
21
|
+
|
|
22
|
+
### Warning Level (30+ pages)
|
|
23
|
+
- ⚠️ **WARNING** at 30+ location pages
|
|
24
|
+
- Enforce 60%+ unique content per page
|
|
25
|
+
- Content must include:
|
|
26
|
+
- Unique local information (landmarks, neighborhoods)
|
|
27
|
+
- Location-specific services or offerings
|
|
28
|
+
- Local team or staff information
|
|
29
|
+
- Genuine customer testimonials from that area
|
|
30
|
+
|
|
31
|
+
### Hard Stop (50+ pages)
|
|
32
|
+
- 🛑 **HARD STOP** at 50+ location pages
|
|
33
|
+
- Require explicit user justification
|
|
34
|
+
- Must demonstrate:
|
|
35
|
+
- Legitimate business presence in each location
|
|
36
|
+
- Unique content strategy for each page
|
|
37
|
+
- Local signals (Google Business Profile, local reviews)
|
|
38
|
+
|
|
39
|
+
### Why This Matters
|
|
40
|
+
Google's doorway page algorithm penalizes programmatic location pages with thin/duplicate content. Signs of doorway pages:
|
|
41
|
+
- Only city/state name changed between pages
|
|
42
|
+
- No unique local information
|
|
43
|
+
- No local business signals
|
|
44
|
+
- Keyword-stuffed URLs
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Safe vs. Risky Programmatic Pages
|
|
49
|
+
|
|
50
|
+
### Safe at Scale ✅
|
|
51
|
+
| Page Type | Why It's Safe |
|
|
52
|
+
|-----------|---------------|
|
|
53
|
+
| Integration pages | Real setup documentation, unique technical content |
|
|
54
|
+
| Template/tool pages | Downloadable assets, unique functionality |
|
|
55
|
+
| Glossary pages | 200+ word unique definitions |
|
|
56
|
+
| Product pages | Unique specs, images, reviews |
|
|
57
|
+
| User profile pages | User-generated unique content |
|
|
58
|
+
|
|
59
|
+
### Penalty Risk ❌
|
|
60
|
+
| Page Type | Why It's Risky |
|
|
61
|
+
|-----------|----------------|
|
|
62
|
+
| Location pages with only city swapped | Duplicate content, doorway pages |
|
|
63
|
+
| "Best [tool] for [industry]" | Often thin, no industry-specific value |
|
|
64
|
+
| "[Competitor] alternative" | Requires genuine comparison data |
|
|
65
|
+
| AI-generated mass content | No unique value, E-E-A-T failure |
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Title Tag Requirements
|
|
70
|
+
|
|
71
|
+
| Aspect | Requirement |
|
|
72
|
+
|--------|-------------|
|
|
73
|
+
| Minimum length | 30 characters |
|
|
74
|
+
| Maximum length | 60 characters (Google truncates ~60) |
|
|
75
|
+
| Primary keyword | Near the beginning |
|
|
76
|
+
| Brand name | At end (if included) |
|
|
77
|
+
| Uniqueness | Each page must have unique title |
|
|
78
|
+
|
|
79
|
+
### Good Examples
|
|
80
|
+
- "Emergency Plumbing Services in Austin | ABC Plumbing"
|
|
81
|
+
- "How to Fix a Leaky Faucet: Step-by-Step Guide"
|
|
82
|
+
- "Enterprise SEO Software | Comprehensive Platform"
|
|
83
|
+
|
|
84
|
+
### Bad Examples
|
|
85
|
+
- "Home" (too short, not descriptive)
|
|
86
|
+
- "Best Plumbing Services for All Your Plumbing Needs in Austin Texas and Surrounding Areas" (too long)
|
|
87
|
+
- "ABC Plumbing - Plumbing - Plumber - Plumbing Services" (keyword stuffing)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Meta Description Requirements
|
|
92
|
+
|
|
93
|
+
| Aspect | Requirement |
|
|
94
|
+
|--------|-------------|
|
|
95
|
+
| Minimum length | 120 characters |
|
|
96
|
+
| Maximum length | 160 characters (Google truncates ~155-160) |
|
|
97
|
+
| Call-to-action | Include compelling CTA |
|
|
98
|
+
| Primary keyword | Include naturally |
|
|
99
|
+
| Uniqueness | Each page must have unique description |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Image Alt Text Requirements
|
|
104
|
+
|
|
105
|
+
| Aspect | Requirement |
|
|
106
|
+
|--------|-------------|
|
|
107
|
+
| Required on | All non-decorative images |
|
|
108
|
+
| Length | 10-125 characters |
|
|
109
|
+
| Content | Describe the image content, not "image" or filename |
|
|
110
|
+
| Keywords | Include naturally where relevant |
|
|
111
|
+
| Decorative images | Use `alt=""` or `role="presentation"` |
|
|
112
|
+
|
|
113
|
+
### Good Examples
|
|
114
|
+
- "Professional plumber repairing kitchen sink faucet"
|
|
115
|
+
- "Red 2024 Toyota Camry sedan front view"
|
|
116
|
+
- "Team meeting in modern office conference room"
|
|
117
|
+
|
|
118
|
+
### Bad Examples
|
|
119
|
+
- "image.jpg" (filename, not description)
|
|
120
|
+
- "plumber plumbing plumber services" (keyword stuffing)
|
|
121
|
+
- "Click here" (not descriptive)
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Internal Linking Guidelines
|
|
126
|
+
|
|
127
|
+
| Page Type | Internal Links Target |
|
|
128
|
+
|-----------|----------------------|
|
|
129
|
+
| Blog post (1,500+ words) | 5-10 internal links |
|
|
130
|
+
| Service page | 3-5 internal links |
|
|
131
|
+
| Category page | Links to all child pages |
|
|
132
|
+
| Product page | 2-4 internal links |
|
|
133
|
+
|
|
134
|
+
### Anchor Text Rules
|
|
135
|
+
- Use descriptive anchor text (not "click here")
|
|
136
|
+
- Vary anchor text (don't always use exact match keywords)
|
|
137
|
+
- Link to relevant, related content
|
|
138
|
+
- Ensure no orphan pages (every page linked from at least one other page)
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Content Freshness Signals
|
|
143
|
+
|
|
144
|
+
| Content Type | Update Frequency |
|
|
145
|
+
|--------------|------------------|
|
|
146
|
+
| News/current events | Within hours/days |
|
|
147
|
+
| Blog posts (evergreen) | Review annually |
|
|
148
|
+
| Product pages | When specs change |
|
|
149
|
+
| Service pages | Review quarterly |
|
|
150
|
+
| Company info | When changes occur |
|
|
151
|
+
|
|
152
|
+
### Required Elements
|
|
153
|
+
- Publication date visible (for articles/blogs)
|
|
154
|
+
- Last updated date (if significantly revised)
|
|
155
|
+
- Changelog for major updates (optional but good)
|