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.

Potentially problematic release.


This version of antigravity-seo-kit might be problematic. Click here for more details.

Files changed (135) hide show
  1. package/.agent/agent.md +96 -0
  2. package/.agent/skills/seo/SKILL.md +153 -0
  3. package/.agent/skills/seo/references/cwv-thresholds.md +108 -0
  4. package/.agent/skills/seo/references/eeat-framework.md +214 -0
  5. package/.agent/skills/seo/references/local-schema-types.md +230 -0
  6. package/.agent/skills/seo/references/local-seo-signals.md +218 -0
  7. package/.agent/skills/seo/references/maps-api-endpoints.md +160 -0
  8. package/.agent/skills/seo/references/maps-free-apis.md +176 -0
  9. package/.agent/skills/seo/references/maps-gbp-checklist.md +150 -0
  10. package/.agent/skills/seo/references/maps-geo-grid.md +154 -0
  11. package/.agent/skills/seo/references/quality-gates.md +155 -0
  12. package/.agent/skills/seo/references/schema-types.md +118 -0
  13. package/.agent/skills/seo/schema/templates.json +213 -0
  14. package/.agent/skills/seo/scripts/analyze_visual.py +217 -0
  15. package/.agent/skills/seo/scripts/capture_screenshot.py +181 -0
  16. package/.agent/skills/seo/scripts/fetch_page.py +196 -0
  17. package/.agent/skills/seo/scripts/parse_html.py +201 -0
  18. package/.agent/skills/seo-audit/SKILL.md +278 -0
  19. package/.agent/skills/seo-competitor-pages/SKILL.md +212 -0
  20. package/.agent/skills/seo-content/SKILL.md +230 -0
  21. package/.agent/skills/seo-dataforseo/SKILL.md +418 -0
  22. package/.agent/skills/seo-geo/SKILL.md +305 -0
  23. package/.agent/skills/seo-google/SKILL.md +405 -0
  24. package/.agent/skills/seo-google/assets/templates/cwv-audit-report.md +48 -0
  25. package/.agent/skills/seo-google/assets/templates/gsc-performance-report.md +44 -0
  26. package/.agent/skills/seo-google/assets/templates/indexation-status-report.md +43 -0
  27. package/.agent/skills/seo-google/references/auth-setup.md +154 -0
  28. package/.agent/skills/seo-google/references/ga4-data-api.md +184 -0
  29. package/.agent/skills/seo-google/references/indexing-api.md +107 -0
  30. package/.agent/skills/seo-google/references/keyword-planner-api.md +66 -0
  31. package/.agent/skills/seo-google/references/nlp-api.md +55 -0
  32. package/.agent/skills/seo-google/references/pagespeed-crux-api.md +204 -0
  33. package/.agent/skills/seo-google/references/rate-limits-quotas.md +75 -0
  34. package/.agent/skills/seo-google/references/search-console-api.md +156 -0
  35. package/.agent/skills/seo-google/references/supplementary-apis.md +99 -0
  36. package/.agent/skills/seo-google/references/youtube-api.md +49 -0
  37. package/.agent/skills/seo-google/scripts/crux_history.py +321 -0
  38. package/.agent/skills/seo-google/scripts/ga4_report.py +478 -0
  39. package/.agent/skills/seo-google/scripts/google_auth.py +795 -0
  40. package/.agent/skills/seo-google/scripts/google_report.py +2273 -0
  41. package/.agent/skills/seo-google/scripts/gsc_inspect.py +340 -0
  42. package/.agent/skills/seo-google/scripts/gsc_query.py +378 -0
  43. package/.agent/skills/seo-google/scripts/indexing_notify.py +313 -0
  44. package/.agent/skills/seo-google/scripts/keyword_planner.py +297 -0
  45. package/.agent/skills/seo-google/scripts/nlp_analyze.py +309 -0
  46. package/.agent/skills/seo-google/scripts/pagespeed_check.py +649 -0
  47. package/.agent/skills/seo-google/scripts/youtube_search.py +355 -0
  48. package/.agent/skills/seo-hreflang/SKILL.md +192 -0
  49. package/.agent/skills/seo-image-gen/SKILL.md +211 -0
  50. package/.agent/skills/seo-image-gen/references/cost-tracking.md +47 -0
  51. package/.agent/skills/seo-image-gen/references/gemini-models.md +200 -0
  52. package/.agent/skills/seo-image-gen/references/mcp-tools.md +115 -0
  53. package/.agent/skills/seo-image-gen/references/post-processing.md +192 -0
  54. package/.agent/skills/seo-image-gen/references/presets.md +69 -0
  55. package/.agent/skills/seo-image-gen/references/prompt-engineering.md +411 -0
  56. package/.agent/skills/seo-image-gen/references/seo-image-presets.md +137 -0
  57. package/.agent/skills/seo-image-gen/scripts/batch.py +97 -0
  58. package/.agent/skills/seo-image-gen/scripts/cost_tracker.py +191 -0
  59. package/.agent/skills/seo-image-gen/scripts/edit.py +141 -0
  60. package/.agent/skills/seo-image-gen/scripts/generate.py +149 -0
  61. package/.agent/skills/seo-image-gen/scripts/presets.py +153 -0
  62. package/.agent/skills/seo-image-gen/scripts/setup_mcp.py +151 -0
  63. package/.agent/skills/seo-image-gen/scripts/validate_setup.py +133 -0
  64. package/.agent/skills/seo-images/SKILL.md +176 -0
  65. package/.agent/skills/seo-local/SKILL.md +381 -0
  66. package/.agent/skills/seo-maps/SKILL.md +328 -0
  67. package/.agent/skills/seo-page/SKILL.md +86 -0
  68. package/.agent/skills/seo-plan/SKILL.md +118 -0
  69. package/.agent/skills/seo-plan/assets/agency.md +175 -0
  70. package/.agent/skills/seo-plan/assets/ecommerce.md +167 -0
  71. package/.agent/skills/seo-plan/assets/generic.md +144 -0
  72. package/.agent/skills/seo-plan/assets/local-service.md +160 -0
  73. package/.agent/skills/seo-plan/assets/publisher.md +153 -0
  74. package/.agent/skills/seo-plan/assets/saas.md +135 -0
  75. package/.agent/skills/seo-programmatic/SKILL.md +171 -0
  76. package/.agent/skills/seo-schema/SKILL.md +223 -0
  77. package/.agent/skills/seo-sitemap/SKILL.md +180 -0
  78. package/.agent/skills/seo-technical/SKILL.md +211 -0
  79. package/.agent/workflows/seo-audit.md +17 -0
  80. package/.agent/workflows/seo-competitor-pages.md +12 -0
  81. package/.agent/workflows/seo-content.md +14 -0
  82. package/.agent/workflows/seo-geo.md +12 -0
  83. package/.agent/workflows/seo-google.md +12 -0
  84. package/.agent/workflows/seo-hreflang.md +12 -0
  85. package/.agent/workflows/seo-images.md +13 -0
  86. package/.agent/workflows/seo-local.md +12 -0
  87. package/.agent/workflows/seo-maps.md +11 -0
  88. package/.agent/workflows/seo-page.md +13 -0
  89. package/.agent/workflows/seo-plan.md +13 -0
  90. package/.agent/workflows/seo-programmatic.md +12 -0
  91. package/.agent/workflows/seo-schema.md +11 -0
  92. package/.agent/workflows/seo-sitemap.md +9 -0
  93. package/.agent/workflows/seo-technical.md +18 -0
  94. package/LICENSE +88 -0
  95. package/README.md +122 -0
  96. package/bin/cli.js +117 -0
  97. package/docs/ARCHITECTURE.md +218 -0
  98. package/docs/COMMANDS.md +184 -0
  99. package/docs/INSTALLATION.md +100 -0
  100. package/docs/MCP-INTEGRATION.md +153 -0
  101. package/docs/TROUBLESHOOTING.md +151 -0
  102. package/docs/superpowers/plans/2026-03-13-github-audit-fixes.md +511 -0
  103. package/extensions/banana/README.md +95 -0
  104. package/extensions/banana/docs/BANANA-SETUP.md +86 -0
  105. package/extensions/banana/install.sh +170 -0
  106. package/extensions/banana/references/cost-tracking.md +47 -0
  107. package/extensions/banana/references/gemini-models.md +200 -0
  108. package/extensions/banana/references/mcp-tools.md +115 -0
  109. package/extensions/banana/references/post-processing.md +192 -0
  110. package/extensions/banana/references/presets.md +69 -0
  111. package/extensions/banana/references/prompt-engineering.md +411 -0
  112. package/extensions/banana/references/seo-image-presets.md +137 -0
  113. package/extensions/banana/scripts/batch.py +97 -0
  114. package/extensions/banana/scripts/cost_tracker.py +191 -0
  115. package/extensions/banana/scripts/edit.py +141 -0
  116. package/extensions/banana/scripts/generate.py +149 -0
  117. package/extensions/banana/scripts/presets.py +153 -0
  118. package/extensions/banana/scripts/setup_mcp.py +151 -0
  119. package/extensions/banana/scripts/validate_setup.py +133 -0
  120. package/extensions/banana/uninstall.sh +43 -0
  121. package/extensions/dataforseo/README.md +169 -0
  122. package/extensions/dataforseo/docs/DATAFORSEO-SETUP.md +74 -0
  123. package/extensions/dataforseo/field-config.json +280 -0
  124. package/extensions/dataforseo/install.ps1 +110 -0
  125. package/extensions/dataforseo/install.sh +161 -0
  126. package/extensions/dataforseo/uninstall.ps1 +35 -0
  127. package/extensions/dataforseo/uninstall.sh +39 -0
  128. package/lib/api.js +190 -0
  129. package/lib/fingerprint.js +68 -0
  130. package/lib/installer.js +486 -0
  131. package/lib/utils.js +254 -0
  132. package/package.json +40 -0
  133. package/pyproject.toml +11 -0
  134. package/requirements-google.txt +15 -0
  135. package/requirements.txt +11 -0
@@ -0,0 +1,184 @@
1
+ # GA4 Data API v1beta Reference
2
+
3
+ ## Overview
4
+
5
+ The Google Analytics Data API v1beta provides programmatic access to GA4 report data. For SEO, the primary use case is organic traffic analysis.
6
+
7
+ **Base URL:** `https://analyticsdata.googleapis.com/v1beta`
8
+
9
+ ## Key Methods
10
+
11
+ | Method | Description |
12
+ |--------|-------------|
13
+ | `properties.runReport` | Run a standard report |
14
+ | `properties.batchRunReports` | Up to 5 reports in one call |
15
+ | `properties.runRealtimeReport` | Last 30 minutes of data |
16
+ | `properties.getMetadata` | Available dimensions and metrics |
17
+ | `properties.checkCompatibility` | Verify dimension/metric combinations |
18
+
19
+ ## runReport Request
20
+
21
+ ```json
22
+ {
23
+ "property": "properties/123456789",
24
+ "dimensions": [
25
+ { "name": "date" },
26
+ { "name": "landingPage" }
27
+ ],
28
+ "metrics": [
29
+ { "name": "sessions" },
30
+ { "name": "totalUsers" }
31
+ ],
32
+ "dateRanges": [
33
+ { "startDate": "28daysAgo", "endDate": "yesterday" }
34
+ ],
35
+ "dimensionFilter": {
36
+ "filter": {
37
+ "fieldName": "sessionDefaultChannelGroup",
38
+ "stringFilter": {
39
+ "matchType": "EXACT",
40
+ "value": "Organic Search"
41
+ }
42
+ }
43
+ },
44
+ "orderBys": [
45
+ { "metric": { "metricName": "sessions" }, "desc": true }
46
+ ],
47
+ "limit": 100,
48
+ "returnPropertyQuota": true
49
+ }
50
+ ```
51
+
52
+ ## SEO-Relevant Dimensions
53
+
54
+ | Dimension | Description |
55
+ |-----------|-------------|
56
+ | `date` | Date in YYYYMMDD format |
57
+ | `pagePath` | Page path (e.g., `/blog/post`) |
58
+ | `landingPage` | Entry page path |
59
+ | `landingPagePlusQueryString` | Entry page with query params |
60
+ | `fullPageUrl` | Full page URL |
61
+ | `pageTitle` | Page title |
62
+ | `sessionSource` | Traffic source (e.g., `google`) |
63
+ | `sessionMedium` | Traffic medium (e.g., `organic`) |
64
+ | `sessionDefaultChannelGroup` | Channel grouping (e.g., `Organic Search`) |
65
+ | `country` | User country |
66
+ | `deviceCategory` | `desktop`, `mobile`, `tablet` |
67
+ | `hostName` | Domain name |
68
+ | `pageReferrer` | Referrer URL |
69
+
70
+ ## SEO-Relevant Metrics
71
+
72
+ | Metric | Description |
73
+ |--------|-------------|
74
+ | `sessions` | Number of sessions |
75
+ | `totalUsers` | Total unique users |
76
+ | `newUsers` | First-time users |
77
+ | `activeUsers` | Users with engagement |
78
+ | `screenPageViews` | Page views |
79
+ | `bounceRate` | Bounce rate (0-1, multiply by 100 for %) |
80
+ | `averageSessionDuration` | Avg duration in seconds |
81
+ | `engagementRate` | Engaged session rate (0-1) |
82
+ | `keyEvents` | Key events (replaced deprecated `conversions`) |
83
+ | `eventCount` | Total event count |
84
+
85
+ ## Filter Expressions
86
+
87
+ ### String Filter
88
+
89
+ ```json
90
+ {
91
+ "filter": {
92
+ "fieldName": "sessionDefaultChannelGroup",
93
+ "stringFilter": {
94
+ "matchType": "EXACT",
95
+ "value": "Organic Search"
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ Match types: `EXACT`, `BEGINS_WITH`, `ENDS_WITH`, `CONTAINS`, `FULL_REGEXP`, `PARTIAL_REGEXP`
102
+
103
+ ### Combining Filters
104
+
105
+ ```json
106
+ {
107
+ "andGroup": {
108
+ "expressions": [
109
+ { "filter": { "fieldName": "country", "stringFilter": { "matchType": "EXACT", "value": "US" }}},
110
+ { "filter": { "fieldName": "deviceCategory", "stringFilter": { "matchType": "EXACT", "value": "mobile" }}}
111
+ ]
112
+ }
113
+ }
114
+ ```
115
+
116
+ Also supports `orGroup` and `notExpression`.
117
+
118
+ ## Date Range Shortcuts
119
+
120
+ | Value | Meaning |
121
+ |-------|---------|
122
+ | `today` | Current day |
123
+ | `yesterday` | Previous day |
124
+ | `NdaysAgo` | N days ago (e.g., `28daysAgo`) |
125
+ | `YYYY-MM-DD` | Specific date |
126
+
127
+ Up to 4 date ranges per request (for period-over-period comparison).
128
+
129
+ ## Token-Based Quotas
130
+
131
+ | Quota | Limit | Scope |
132
+ |-------|-------|-------|
133
+ | Daily tokens | 25,000 | Per property per project |
134
+ | Hourly tokens | 5,000 | Per property per project |
135
+ | Concurrent requests | 10 | Per property per project |
136
+ | Hourly tokens (project-wide) | 1,250 | Per project per property per hour |
137
+
138
+ Set `returnPropertyQuota: true` to monitor consumption. Simple reports cost ~1-10 tokens; complex ones up to ~100.
139
+
140
+ ## Python Example
141
+
142
+ ```python
143
+ from google.analytics.data_v1beta import BetaAnalyticsDataClient
144
+ from google.analytics.data_v1beta.types import (
145
+ DateRange, Dimension, Filter, FilterExpression,
146
+ Metric, OrderBy, RunReportRequest,
147
+ )
148
+ from google.oauth2 import service_account
149
+
150
+ credentials = service_account.Credentials.from_service_account_file(
151
+ "service_account.json",
152
+ scopes=["https://www.googleapis.com/auth/analytics.readonly"],
153
+ )
154
+
155
+ client = BetaAnalyticsDataClient(credentials=credentials)
156
+
157
+ request = RunReportRequest(
158
+ property="properties/123456789",
159
+ dimensions=[Dimension(name="landingPage")],
160
+ metrics=[Metric(name="sessions"), Metric(name="totalUsers")],
161
+ date_ranges=[DateRange(start_date="28daysAgo", end_date="yesterday")],
162
+ dimension_filter=FilterExpression(
163
+ filter=Filter(
164
+ field_name="sessionDefaultChannelGroup",
165
+ string_filter=Filter.StringFilter(
166
+ match_type=Filter.StringFilter.MatchType.EXACT,
167
+ value="Organic Search",
168
+ ),
169
+ )
170
+ ),
171
+ order_bys=[OrderBy(metric=OrderBy.MetricOrderBy(metric_name="sessions"), desc=True)],
172
+ limit=50,
173
+ return_property_quota=True,
174
+ )
175
+
176
+ response = client.run_report(request)
177
+ for row in response.rows:
178
+ print(f"{row.dimension_values[0].value}: {row.metric_values[0].value} sessions")
179
+ ```
180
+
181
+ ## Authentication
182
+ - **Scope:** `https://www.googleapis.com/auth/analytics.readonly`
183
+ - Service account must have **Viewer** role in GA4 property
184
+ - Add via GA4 Admin > Property Access Management
@@ -0,0 +1,107 @@
1
+ # Google Indexing API v3 Reference
2
+
3
+ ## Overview
4
+
5
+ The Indexing API allows you to notify Google when pages are added or removed.
6
+
7
+ **IMPORTANT:** Officially restricted to pages with **JobPosting** or **BroadcastEvent/VideoObject** structured data. Google may process other page types, but provides no guarantees. Always inform users of this limitation.
8
+
9
+ ## Endpoints
10
+
11
+ ### Publish Notification
12
+
13
+ **`POST https://indexing.googleapis.com/v3/urlNotifications:publish`**
14
+
15
+ ```json
16
+ {
17
+ "url": "https://example.com/jobs/software-engineer",
18
+ "type": "URL_UPDATED"
19
+ }
20
+ ```
21
+
22
+ | Field | Values |
23
+ |-------|--------|
24
+ | `url` | The fully qualified URL |
25
+ | `type` | `URL_UPDATED` (page added/changed), `URL_DELETED` (page removed) |
26
+
27
+ **Response:**
28
+ ```json
29
+ {
30
+ "urlNotificationMetadata": {
31
+ "url": "https://example.com/jobs/software-engineer",
32
+ "latestUpdate": {
33
+ "url": "https://example.com/jobs/software-engineer",
34
+ "type": "URL_UPDATED",
35
+ "notifyTime": "2026-03-27T10:00:00Z"
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ### Get Notification Metadata
42
+
43
+ **`GET https://indexing.googleapis.com/v3/urlNotifications/metadata?url={ENCODED_URL}`**
44
+
45
+ Returns `latestUpdate` and `latestRemove` timestamps for the URL.
46
+
47
+ ### Batch Requests
48
+
49
+ **`POST https://indexing.googleapis.com/batch`**
50
+
51
+ Up to **100 URLs** per batch request using `multipart/mixed` format:
52
+
53
+ ```
54
+ POST /batch HTTP/1.1
55
+ Content-Type: multipart/mixed; boundary=batch_boundary
56
+
57
+ --batch_boundary
58
+ Content-Type: application/http
59
+ Content-ID: <item1>
60
+
61
+ POST /v3/urlNotifications:publish HTTP/1.1
62
+ Content-Type: application/json
63
+
64
+ {"url": "https://example.com/jobs/1", "type": "URL_UPDATED"}
65
+ --batch_boundary
66
+ Content-Type: application/http
67
+ Content-ID: <item2>
68
+
69
+ POST /v3/urlNotifications:publish HTTP/1.1
70
+ Content-Type: application/json
71
+
72
+ {"url": "https://example.com/jobs/2", "type": "URL_UPDATED"}
73
+ --batch_boundary--
74
+ ```
75
+
76
+ ## Authentication
77
+
78
+ - **Scope:** `https://www.googleapis.com/auth/indexing`
79
+ - **Auth type:** Service account (OAuth 2.0)
80
+ - The service account must be **Owner** in Google Search Console for the target domain
81
+
82
+ ## Quotas
83
+
84
+ | Limit | Value | Scope |
85
+ |-------|-------|-------|
86
+ | Publish requests | **200/day** (default) | Per project |
87
+ | Read-only requests | 180/min | Per project |
88
+ | Total requests | 380/min | Per project |
89
+
90
+ Request a quota increase: [Indexing API Quota Increase Form](https://developers.google.com/search/apis/indexing-api/v3/quota-increase)
91
+
92
+ ## Error Codes
93
+
94
+ | Code | Meaning | Action |
95
+ |------|---------|--------|
96
+ | 400 | Malformed URL or request body | Check URL format |
97
+ | 403 | Permission denied or quota exceeded | Add service account as Owner in GSC, or check quota |
98
+ | 429 | Rate limit exceeded | Back off and retry with exponential delay |
99
+ | 500/503 | Server error | Retry with exponential backoff |
100
+
101
+ ## Best Practices
102
+
103
+ 1. Submit only URLs with actual content changes (don't spam updates)
104
+ 2. Use `URL_DELETED` only when a page is permanently removed (returns 404/410)
105
+ 3. Track daily quota usage -- the 200/day limit resets at midnight Pacific Time
106
+ 4. For large-scale indexing, use XML sitemaps + Search Console instead
107
+ 5. Batch requests count individually against the daily quota (100 batch = 100 quota)
@@ -0,0 +1,66 @@
1
+ # Google Ads API - Keyword Planner Reference
2
+
3
+ Gold-standard source for keyword search volume. DataForSEO gets its volume data from Google Ads -- this cuts out the middleman.
4
+
5
+ ## Prerequisites (More Complex Than Other Google APIs)
6
+
7
+ 1. **Google Ads Manager Account** -- create at ads.google.com (free to create)
8
+ 2. **Developer Token** -- apply at Google Ads API Center (requires Basic access approval)
9
+ 3. **OAuth 2.0 credentials** -- reuse existing OAuth client from seo-google config
10
+ 4. **For exact volumes**: Run a minimal campaign (~$5-10/day). Without spend, volumes are bucketed ranges ("1K-10K")
11
+
12
+ ## Key Methods
13
+
14
+ ### GenerateKeywordIdeas
15
+ Generate keyword suggestions from seed terms.
16
+
17
+ **Returns per keyword:**
18
+ - `text`: Keyword string
19
+ - `avg_monthly_searches`: Average monthly volume (exact if spending, bucketed if not)
20
+ - `competition`: LOW / MEDIUM / HIGH (for ads, not organic)
21
+ - `competition_index`: 0-100 competition score
22
+ - `low_top_of_page_bid_micros`: ~20th percentile CPC in micros
23
+ - `high_top_of_page_bid_micros`: ~80th percentile CPC in micros
24
+ - `monthly_search_volumes[]`: Per-month volume for last 12 months
25
+
26
+ ### GenerateKeywordHistoricalMetrics
27
+ Get volume data for specific keywords.
28
+
29
+ Same return fields as above but for exact keyword list instead of suggestions.
30
+
31
+ ### GenerateKeywordForecastMetrics
32
+ Predict clicks, impressions, and cost for keywords.
33
+
34
+ ## Configuration
35
+
36
+ Add to `~/.config/claude-seo/google-api.json`:
37
+
38
+ ```json
39
+ {
40
+ "ads_developer_token": "YOUR_DEV_TOKEN",
41
+ "ads_customer_id": "123-456-7890",
42
+ "ads_login_customer_id": "123-456-7890"
43
+ }
44
+ ```
45
+
46
+ ## Rate Limits
47
+
48
+ - Keyword Planning requests are more strictly rate-limited than other Ads API services
49
+ - Exact QPM/QPS not publicly documented
50
+ - Google recommends caching results
51
+
52
+ ## Python Library
53
+
54
+ ```bash
55
+ pip install google-ads
56
+ ```
57
+
58
+ Uses `google-ads` library (separate from `google-api-python-client`).
59
+
60
+ ## Important Notes
61
+
62
+ - **Volume accuracy**: Without active ad spend, Google returns bucketed ranges ("1K-10K", "10K-100K") instead of exact numbers like "14,800"
63
+ - **Competition score**: Measures advertiser competition for ads, NOT organic ranking difficulty
64
+ - **CPC bids**: Reflect what advertisers pay, useful for estimating keyword commercial value
65
+ - **Location targeting**: Use location IDs (2840 = United States, 2826 = United Kingdom)
66
+ - **Language targeting**: Use language IDs (1000 = English, 1003 = Spanish)
@@ -0,0 +1,55 @@
1
+ # Google Cloud Natural Language API Reference
2
+
3
+ NLP analysis enhances E-E-A-T scoring by measuring entity coverage, content sentiment, and topic classification using Google's own taxonomy.
4
+
5
+ ## Endpoint
6
+
7
+ `POST https://language.googleapis.com/v2/documents:annotateText?key={API_KEY}`
8
+
9
+ ## Features
10
+
11
+ | Feature | What It Does | SEO Use |
12
+ |---------|-------------|---------|
13
+ | `extractEntities` | Extract people, orgs, places, events with salience scores | Topic coverage depth, entity optimization |
14
+ | `extractDocumentSentiment` | Document + sentence-level sentiment score/magnitude | Content tone assessment |
15
+ | `classifyText` | Map content to 700+ Google categories | Topic relevance verification |
16
+ | `moderateText` | Content safety/moderation categories | Content quality flags |
17
+
18
+ ## Entity Types
19
+
20
+ PERSON, LOCATION, ORGANIZATION, EVENT, WORK_OF_ART, CONSUMER_GOOD, OTHER, PHONE_NUMBER, ADDRESS, DATE, NUMBER, PRICE
21
+
22
+ Each entity includes:
23
+ - `name`: Entity text
24
+ - `type`: Entity type
25
+ - `salience`: Importance score (0-1, higher = more relevant)
26
+ - `sentiment`: Per-entity sentiment (score + magnitude)
27
+ - `metadata`: Wikipedia URL, MID (Knowledge Graph ID)
28
+ - `mentions`: Occurrences in the text
29
+
30
+ ## Sentiment Scoring
31
+
32
+ - **Score**: -1.0 (negative) to +1.0 (positive)
33
+ - **Magnitude**: 0 to infinity (emotional intensity, higher = more emotional)
34
+ - Neutral content: score ~0, low magnitude
35
+ - Mixed content: score ~0, HIGH magnitude (both positive and negative)
36
+
37
+ ## Pricing
38
+
39
+ | Feature | Free/month | Paid (per 1K chars) |
40
+ |---------|-----------|-------------------|
41
+ | Entity Analysis | 5,000 units | $0.001 |
42
+ | Sentiment Analysis | 5,000 units | $0.001 |
43
+ | Content Classification | 30,000 units | $0.002 |
44
+ | Text Moderation | 50,000 units | $0.0005 |
45
+
46
+ One "unit" = 1,000 characters. Free tier resets monthly.
47
+
48
+ ## Enable the API
49
+
50
+ 1. Go to [console.cloud.google.com/apis/library](https://console.cloud.google.com/apis/library)
51
+ 2. Search for "Cloud Natural Language API"
52
+ 3. Click Enable
53
+ 4. **Billing must be enabled** on the project (free tier still applies)
54
+
55
+ Uses the same API key as PSI/CrUX.
@@ -0,0 +1,204 @@
1
+ # PageSpeed Insights v5 + CrUX API Reference
2
+
3
+ ## Table of Contents
4
+ 1. [PageSpeed Insights v5](#pagespeed-insights-v5)
5
+ 2. [CrUX API (Daily)](#crux-api-daily)
6
+ 3. [CrUX History API (Weekly)](#crux-history-api-weekly)
7
+ 4. [Core Web Vitals Thresholds](#core-web-vitals-thresholds)
8
+
9
+ ---
10
+
11
+ ## PageSpeed Insights v5
12
+
13
+ **Endpoint:** `GET https://www.googleapis.com/pagespeedonline/v5/runPagespeed`
14
+
15
+ ### Parameters
16
+
17
+ | Param | Type | Description |
18
+ |-------|------|-------------|
19
+ | `url` | string | Required. URL to analyze. |
20
+ | `category` | string | `ACCESSIBILITY`, `BEST_PRACTICES`, `PERFORMANCE`, `SEO`. Can specify multiple. |
21
+ | `strategy` | string | `DESKTOP` or `MOBILE` (default). |
22
+ | `locale` | string | Locale for text (e.g., `en`). |
23
+ | `key` | string | API key. Optional but recommended for quota. |
24
+
25
+ ### Response Structure
26
+
27
+ ```
28
+ {
29
+ "id": "https://example.com/",
30
+ "loadingExperience": { ... }, // URL-level CrUX data
31
+ "originLoadingExperience": { ... }, // Origin-level CrUX data
32
+ "lighthouseResult": {
33
+ "categories": {
34
+ "performance": { "score": 0.85 },
35
+ "accessibility": { "score": 0.92 },
36
+ "best-practices": { "score": 0.88 },
37
+ "seo": { "score": 0.95 }
38
+ },
39
+ "audits": { ... } // Individual audit results
40
+ },
41
+ "analysisUTCTimestamp": "2026-03-27T..."
42
+ }
43
+ ```
44
+
45
+ ### Field Data Metrics (in loadingExperience)
46
+
47
+ | PSI Key | CrUX Metric | Unit |
48
+ |---------|-------------|------|
49
+ | `LARGEST_CONTENTFUL_PAINT_MS` | LCP | ms |
50
+ | `INTERACTION_TO_NEXT_PAINT` | INP | ms |
51
+ | `CUMULATIVE_LAYOUT_SHIFT_SCORE` | CLS | unitless |
52
+ | `FIRST_CONTENTFUL_PAINT_MS` | FCP | ms |
53
+ | `EXPERIMENTAL_TIME_TO_FIRST_BYTE` | TTFB | ms |
54
+
55
+ Each metric contains: `percentile` (p75), `distributions[]` ({min, max, proportion}), `category` (FAST/AVERAGE/SLOW/NONE).
56
+
57
+ ### Key Lighthouse Audit IDs
58
+
59
+ `first-contentful-paint`, `largest-contentful-paint`, `total-blocking-time`, `cumulative-layout-shift`, `speed-index`, `interactive`
60
+
61
+ ### Rate Limits
62
+ - 25,000 QPD with API key
63
+ - 240 QPM
64
+ - Free, no billing required
65
+
66
+ ### Note on Field Data Migration
67
+ Google is migrating CrUX field data out of PSI. For field data, prefer the CrUX API directly. Use PSI primarily for Lighthouse lab data.
68
+
69
+ ---
70
+
71
+ ## CrUX API (Daily)
72
+
73
+ **Endpoint:** `POST https://chromeuxreport.googleapis.com/v1/records:queryRecord?key={API_KEY}`
74
+
75
+ ### Request
76
+
77
+ ```json
78
+ {
79
+ "origin": "https://example.com",
80
+ "formFactor": "PHONE",
81
+ "metrics": ["largest_contentful_paint", "interaction_to_next_paint", "cumulative_layout_shift"]
82
+ }
83
+ ```
84
+
85
+ | Field | Description |
86
+ |-------|-------------|
87
+ | `origin` | Origin URL (mutually exclusive with `url`) |
88
+ | `url` | Specific page URL (mutually exclusive with `origin`) |
89
+ | `formFactor` | `DESKTOP`, `PHONE`, `TABLET` (optional, omit for all) |
90
+ | `metrics` | Array of metric names (optional, omit for all) |
91
+
92
+ ### Available Metrics
93
+
94
+ | Metric | Type | Notes |
95
+ |--------|------|-------|
96
+ | `largest_contentful_paint` | int (ms) | Core Web Vital |
97
+ | `interaction_to_next_paint` | int (ms) | Core Web Vital (replaced FID) |
98
+ | `cumulative_layout_shift` | **string** | Core Web Vital. **String-encoded!** Parse carefully. |
99
+ | `first_contentful_paint` | int (ms) | |
100
+ | `experimental_time_to_first_byte` | int (ms) | |
101
+ | `round_trip_time` | int (ms) | Replaced effectiveConnectionType (Feb 2025) |
102
+ | `navigation_types` | fractions | navigate, navigate_cache, reload, etc. |
103
+ | `form_factors` | fractions | desktop/phone/tablet distribution |
104
+
105
+ ### Response
106
+
107
+ ```json
108
+ {
109
+ "record": {
110
+ "key": { "origin": "https://example.com" },
111
+ "metrics": {
112
+ "largest_contentful_paint": {
113
+ "histogram": [
114
+ { "start": 0, "end": 2500, "density": 0.72 },
115
+ { "start": 2500, "end": 4000, "density": 0.18 },
116
+ { "start": 4000, "density": 0.10 }
117
+ ],
118
+ "percentiles": { "p75": 2100 }
119
+ },
120
+ "cumulative_layout_shift": {
121
+ "percentiles": { "p75": "0.05" }
122
+ }
123
+ },
124
+ "collectionPeriod": {
125
+ "firstDate": { "year": 2026, "month": 2, "day": 27 },
126
+ "lastDate": { "year": 2026, "month": 3, "day": 26 }
127
+ }
128
+ }
129
+ }
130
+ ```
131
+
132
+ ### Important
133
+ - **CLS p75 is a string** (e.g., `"0.05"` not `0.05`). Always parse as float from string.
134
+ - Last histogram bin has **no `end`** (extends to infinity).
135
+ - Densities sum to approximately 1.0.
136
+ - **404** = no data (insufficient Chrome traffic). Not an auth error.
137
+ - Updated daily ~04:00 UTC with ~2 day lag.
138
+
139
+ ### Rate Limits
140
+ - 150 QPM shared between CrUX and CrUX History APIs
141
+ - Free, no paid increase available
142
+
143
+ ---
144
+
145
+ ## CrUX History API (Weekly)
146
+
147
+ **Endpoint:** `POST https://chromeuxreport.googleapis.com/v1/records:queryHistoryRecord?key={API_KEY}`
148
+
149
+ Same request format as CrUX API. Returns up to **25 weekly collection periods**.
150
+
151
+ ### Response Differences from CrUX API
152
+
153
+ Instead of single values, returns timeseries:
154
+
155
+ ```json
156
+ {
157
+ "record": {
158
+ "metrics": {
159
+ "largest_contentful_paint": {
160
+ "histogramTimeseries": [
161
+ { "start": 0, "end": 2500, "densities": [0.70, 0.71, 0.72, ...] },
162
+ { "start": 2500, "end": 4000, "densities": [0.19, 0.18, 0.18, ...] },
163
+ { "start": 4000, "densities": [0.11, 0.11, 0.10, ...] }
164
+ ],
165
+ "percentilesTimeseries": {
166
+ "p75s": [2200, 2150, 2100, ...]
167
+ }
168
+ }
169
+ },
170
+ "collectionPeriods": [
171
+ {
172
+ "firstDate": { "year": 2025, "month": 9, "day": 29 },
173
+ "lastDate": { "year": 2025, "month": 10, "day": 26 }
174
+ },
175
+ ...
176
+ ]
177
+ }
178
+ }
179
+ ```
180
+
181
+ ### NaN Handling
182
+ - `"NaN"` string for densities in ineligible periods
183
+ - `null` for percentile values in ineligible periods
184
+ - Always check for these before numeric operations
185
+
186
+ ### Update Schedule
187
+ - Updated **Mondays** ~04:00 UTC
188
+ - Each period = 28-day rolling average ending on a Sunday
189
+
190
+ ---
191
+
192
+ ## Core Web Vitals Thresholds
193
+
194
+ Current as of March 2026. INP replaced FID on March 12, 2024.
195
+
196
+ | Metric | Good | Needs Improvement | Poor |
197
+ |--------|------|-------------------|------|
198
+ | **LCP** | ≤ 2,500ms | 2,500–4,000ms | > 4,000ms |
199
+ | **INP** | ≤ 200ms | 200–500ms | > 500ms |
200
+ | **CLS** | ≤ 0.1 | 0.1–0.25 | > 0.25 |
201
+ | **FCP** | ≤ 1,800ms | 1,800–3,000ms | > 3,000ms |
202
+ | **TTFB** | ≤ 800ms | 800–1,800ms | > 1,800ms |
203
+
204
+ FID was fully removed from Chrome tools (CrUX, PSI, Lighthouse) on September 9, 2024. Never reference FID in outputs.
@@ -0,0 +1,75 @@
1
+ # Google API Rate Limits & Quotas
2
+
3
+ ## Consolidated Quota Table
4
+
5
+ | API | Per-Minute | Per-Day | Cost | Auth Type | Scope |
6
+ |-----|-----------|---------|------|-----------|-------|
7
+ | GSC Search Analytics | 1,200 QPM/user, 1,200 QPM/site | 30M QPD/project | Free | Service Account | Per user + per site |
8
+ | GSC URL Inspection | 600 QPM/site | 2,000 QPD/site | Free | Service Account | Per site |
9
+ | GSC Sitemaps | Standard | Standard | Free | Service Account | Per site |
10
+ | PageSpeed Insights v5 | 240 QPM | 25,000 QPD | Free | API Key | Per project |
11
+ | CrUX API | 150 QPM (shared) | Unlimited | Free | API Key | Per project |
12
+ | CrUX History API | 150 QPM (shared with CrUX) | Unlimited | Free | API Key | Per project |
13
+ | Indexing API | 380 RPM total, 180 read/min | 200 publish/day | Free | Service Account | Per project |
14
+ | GA4 Data API | 10 concurrent | ~25K tokens/day | Free | Service Account | Per property/project |
15
+ | Knowledge Graph | -- | 100,000 QPD | Free | API Key | Per project |
16
+ | Custom Search | -- | 10,000 QPD max | 100 free, $5/1K | API Key | Per project |
17
+ | Web Risk | 6,000 QPM | 100K/month | Free tier | API Key | Per project |
18
+
19
+ **Key distinction:** "Per site" quotas are scoped to a specific GSC property. "Per project" quotas are shared across all properties in a GCP project. "Per user" quotas are per authenticated user (service account).
20
+
21
+ ## Exponential Backoff Strategy
22
+
23
+ When receiving 429 or 5xx errors:
24
+
25
+ ```
26
+ Attempt 1: wait 1 second
27
+ Attempt 2: wait 2 seconds
28
+ Attempt 3: wait 4 seconds
29
+ Attempt 4: wait 8 seconds
30
+ Attempt 5: wait 16 seconds
31
+ Max: give up after 5 retries
32
+ ```
33
+
34
+ Add random jitter (0-500ms) to each wait to avoid thundering herd.
35
+
36
+ ## Common Error Codes
37
+
38
+ | Code | Meaning | Applies To | Action |
39
+ |------|---------|------------|--------|
40
+ | 400 | Bad request | All | Check URL format, request body |
41
+ | 401 | Unauthorized | Service Account APIs | Refresh credentials |
42
+ | 403 | Forbidden | GSC, GA4, Indexing | Check permissions (service account access) |
43
+ | 404 | Not found | CrUX, GSC | Insufficient traffic (CrUX) or invalid property (GSC) |
44
+ | 429 | Rate limited | All | Backoff and retry. Check Retry-After header. |
45
+ | 500 | Server error | All | Retry with backoff |
46
+ | 503 | Service unavailable | All | Retry with backoff |
47
+
48
+ ## Retry-After Header
49
+
50
+ Some Google APIs return a `Retry-After` header with 429 responses. When present, use this value (in seconds) instead of exponential backoff.
51
+
52
+ ## GA4 Token Budgeting
53
+
54
+ GA4 uses a token system rather than simple request counts:
55
+ - Simple 1-dimension, 1-metric report: ~1-5 tokens
56
+ - Complex multi-dimension, multi-metric: ~10-100 tokens
57
+ - Set `returnPropertyQuota: true` to monitor consumption
58
+ - Daily limit: 25,000 tokens per property per project
59
+ - Hourly limit: 5,000 tokens per property per project
60
+ - Concurrent: max 10 simultaneous requests
61
+
62
+ ## CrUX Shared Quota
63
+
64
+ The CrUX API and CrUX History API share the same 150 QPM quota per project. Plan accordingly if querying both APIs in the same workflow.
65
+
66
+ ## Cost Summary
67
+
68
+ **All APIs used by seo-google are free** at normal usage levels. No billing is required for:
69
+ - PSI, CrUX, CrUX History (API key, unlimited free)
70
+ - GSC (service account, 30M QPD)
71
+ - Indexing API (service account, 200 publish/day)
72
+ - GA4 Data API (service account, 25K tokens/day)
73
+ - Knowledge Graph (API key, 100K QPD)
74
+
75
+ Only Custom Search and Web Risk have paid tiers at high volumes.