pagespeed 1.2.2__tar.gz

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.
@@ -0,0 +1,186 @@
1
+ # Created by https://www.toptal.com/developers/gitignore/api/node,macos
2
+ # Edit at https://www.toptal.com/developers/gitignore?templates=node,macos
3
+
4
+ ### macOS ###
5
+ # General
6
+ .DS_Store
7
+ .AppleDouble
8
+ .LSOverride
9
+
10
+ # Icon must end with two \r
11
+ Icon
12
+
13
+
14
+ # Thumbnails
15
+ ._*
16
+
17
+ # Files that might appear in the root of a volume
18
+ .DocumentRevisions-V100
19
+ .fseventsd
20
+ .Spotlight-V100
21
+ .TemporaryItems
22
+ .Trashes
23
+ .VolumeIcon.icns
24
+ .com.apple.timemachine.donotpresent
25
+
26
+ # Directories potentially created on remote AFP share
27
+ .AppleDB
28
+ .AppleDesktop
29
+ Network Trash Folder
30
+ Temporary Items
31
+ .apdisk
32
+
33
+ ### macOS Patch ###
34
+ # iCloud generated files
35
+ *.icloud
36
+
37
+ ### Node ###
38
+ # Logs
39
+ logs
40
+ *.log
41
+ npm-debug.log*
42
+ yarn-debug.log*
43
+ yarn-error.log*
44
+ lerna-debug.log*
45
+ .pnpm-debug.log*
46
+
47
+ # Diagnostic reports (https://nodejs.org/api/report.html)
48
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
49
+
50
+ # Runtime data
51
+ pids
52
+ *.pid
53
+ *.seed
54
+ *.pid.lock
55
+
56
+ # Directory for instrumented libs generated by jscoverage/JSCover
57
+ lib-cov
58
+
59
+ # Coverage directory used by tools like istanbul
60
+ coverage
61
+ *.lcov
62
+
63
+ # nyc test coverage
64
+ .nyc_output
65
+
66
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
67
+ .grunt
68
+
69
+ # Bower dependency directory (https://bower.io/)
70
+ bower_components
71
+
72
+ # node-waf configuration
73
+ .lock-wscript
74
+
75
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
76
+ build/Release
77
+
78
+ # Dependency directories
79
+ node_modules/
80
+ jspm_packages/
81
+
82
+ # Snowpack dependency directory (https://snowpack.dev/)
83
+ web_modules/
84
+
85
+ # TypeScript cache
86
+ *.tsbuildinfo
87
+
88
+ # Optional npm cache directory
89
+ .npm
90
+
91
+ # Optional eslint cache
92
+ .eslintcache
93
+
94
+ # Optional stylelint cache
95
+ .stylelintcache
96
+
97
+ # Microbundle cache
98
+ .rpt2_cache/
99
+ .rts2_cache_cjs/
100
+ .rts2_cache_es/
101
+ .rts2_cache_umd/
102
+
103
+ # Optional REPL history
104
+ .node_repl_history
105
+
106
+ # Output of 'npm pack'
107
+ *.tgz
108
+
109
+ # Yarn Integrity file
110
+ .yarn-integrity
111
+
112
+ # dotenv environment variable files
113
+ .env
114
+ .env.development.local
115
+ .env.test.local
116
+ .env.production.local
117
+ .env.local
118
+
119
+ # parcel-bundler cache (https://parceljs.org/)
120
+ .cache
121
+ .parcel-cache
122
+
123
+ # Next.js build output
124
+ .next
125
+ out
126
+
127
+ # Nuxt.js build / generate output
128
+ .nuxt
129
+ dist
130
+
131
+ # Gatsby files
132
+ .cache/
133
+ # Comment in the public line in if your project uses Gatsby and not Next.js
134
+ # https://nextjs.org/blog/next-9-1#public-directory-support
135
+ # public
136
+
137
+ # vuepress build output
138
+ .vuepress/dist
139
+
140
+ # vuepress v2.x temp and cache directory
141
+ .temp
142
+
143
+ # Docusaurus cache and generated files
144
+ .docusaurus
145
+
146
+ # Serverless directories
147
+ .serverless/
148
+
149
+ # FuseBox cache
150
+ .fusebox/
151
+
152
+ # DynamoDB Local files
153
+ .dynamodb/
154
+
155
+ # TernJS port file
156
+ .tern-port
157
+
158
+ # Stores VSCode versions used for testing VSCode extensions
159
+ .vscode-test
160
+
161
+ # yarn v2
162
+ .yarn/cache
163
+ .yarn/unplugged
164
+ .yarn/build-state.yml
165
+ .yarn/install-state.gz
166
+ .pnp.*
167
+
168
+ ### Node Patch ###
169
+ # Serverless Webpack directories
170
+ .webpack/
171
+
172
+ # Optional stylelint cache
173
+
174
+ # SvelteKit build / generate output
175
+ .svelte-kit
176
+
177
+ # End of https://www.toptal.com/developers/gitignore/api/node,macos
178
+ __pycache__/
179
+ *.pyc
180
+ *.pyo
181
+ *.pyd
182
+ .Python
183
+ dist/
184
+ build/
185
+ *.egg-info/
186
+ .claude/settings.local.json
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Otter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,399 @@
1
+ Metadata-Version: 2.4
2
+ Name: pagespeed
3
+ Version: 1.2.2
4
+ Summary: CLI tool for batch Google PageSpeed Insights analysis with CSV/JSON/HTML reports
5
+ Project-URL: Homepage, https://github.com/volkanunsal/pagespeed
6
+ Project-URL: Repository, https://github.com/volkanunsal/pagespeed
7
+ Project-URL: Issues, https://github.com/volkanunsal/pagespeed/issues
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: core-web-vitals,lighthouse,pagespeed,performance,web-vitals
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
15
+ Requires-Python: >=3.13
16
+ Requires-Dist: pandas
17
+ Requires-Dist: requests
18
+ Description-Content-Type: text/markdown
19
+
20
+ # PageSpeed Insights Batch Analysis Tool
21
+
22
+ A command-line tool that automates Google PageSpeed Insights analysis across multiple URLs, extracting performance metrics (lab + field data) into structured CSV, JSON, and HTML reports.
23
+
24
+ ## Installation
25
+
26
+ ### Run instantly with `uvx` (recommended, no install needed)
27
+
28
+ ```bash
29
+ uvx pagespeed quick-check https://example.com
30
+ ```
31
+
32
+ ### Install with `pip` or `pipx`
33
+
34
+ ```bash
35
+ pip install pagespeed
36
+ pagespeed quick-check https://example.com
37
+ ```
38
+
39
+ ### Run from URL (just needs `uv`)
40
+
41
+ ```bash
42
+ uv run https://raw.githubusercontent.com/volkanunsal/pagespeed/main/pagespeed_insights_tool.py quick-check https://example.com
43
+ ```
44
+
45
+ ### Development
46
+
47
+ ```bash
48
+ git clone https://github.com/volkanunsal/pagespeed.git
49
+ cd pagespeed
50
+ uv run pagespeed_insights_tool.py quick-check https://example.com
51
+ ```
52
+
53
+ ## Prerequisites
54
+
55
+ - **Python 3.13+**
56
+ - **Google API key** (optional) — without one, you're limited to ~25 queries/day; with one, ~25,000/day
57
+
58
+ ## Getting an API Key
59
+
60
+ 1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
61
+ 2. Create a new project (or select an existing one)
62
+ 3. Navigate to **APIs & Services > Library**
63
+ 4. Search for **PageSpeed Insights API** and enable it
64
+ 5. Go to **APIs & Services > Credentials**
65
+ 6. Click **Create Credentials > API Key**
66
+ 7. Copy the key and set it:
67
+ ```bash
68
+ export PAGESPEED_API_KEY=your_key_here
69
+ ```
70
+ Or add it to your `pagespeed.toml` config file (see [Configuration](#configuration)).
71
+
72
+ ## Usage
73
+
74
+ ### `quick-check` — Fast single-URL spot check
75
+
76
+ Prints a formatted report to the terminal. No files written.
77
+
78
+ ```bash
79
+ # Mobile only (default)
80
+ pagespeed quick-check https://www.google.com
81
+
82
+ # Both mobile and desktop
83
+ pagespeed quick-check https://www.google.com --strategy both
84
+
85
+ # With specific categories
86
+ pagespeed quick-check https://www.google.com --categories performance accessibility
87
+ ```
88
+
89
+ Sample output:
90
+
91
+ ```
92
+ ============================================================
93
+ URL: https://www.google.com
94
+ Strategy: mobile
95
+ ============================================================
96
+ Performance Score: 92/100 (GOOD)
97
+
98
+ --- Lab Data ---
99
+ First Contentful Paint............. 1200ms
100
+ Largest Contentful Paint........... 1800ms
101
+ Cumulative Layout Shift............ 0.0100
102
+ Speed Index........................ 1500ms
103
+ Total Blocking Time................ 150ms
104
+ Time to Interactive................ 2100ms
105
+ ```
106
+
107
+ ### `audit` — Full batch analysis
108
+
109
+ Analyzes multiple URLs and writes CSV/JSON reports.
110
+
111
+ ```bash
112
+ # From a file of URLs
113
+ pagespeed audit -f urls.txt
114
+
115
+ # Multiple strategies and output formats
116
+ pagespeed audit -f urls.txt --strategy both --output-format both
117
+
118
+ # Inline URLs with custom output path
119
+ pagespeed audit https://a.com https://b.com -o report
120
+
121
+ # With a named profile
122
+ pagespeed audit -f urls.txt --profile full
123
+
124
+ # Piped input
125
+ cat urls.txt | pagespeed audit
126
+ ```
127
+
128
+ The URL file is one URL per line. Lines starting with `#` are comments:
129
+
130
+ ```
131
+ # Main pages
132
+ https://example.com
133
+ https://example.com/about
134
+ https://example.com/contact
135
+ ```
136
+
137
+ ### `compare` — Compare two reports
138
+
139
+ Loads two previous report files and shows per-URL score changes.
140
+
141
+ ```bash
142
+ # Compare before and after
143
+ pagespeed compare before.csv after.csv
144
+
145
+ # Custom threshold (flag changes >= 10%)
146
+ pagespeed compare --threshold 10 old.json new.json
147
+ ```
148
+
149
+ Output flags regressions with `!!` and improvements with `++`.
150
+
151
+ ### `report` — Generate HTML dashboard
152
+
153
+ Creates a self-contained HTML report from a results file.
154
+
155
+ ```bash
156
+ # Generate HTML from CSV results
157
+ pagespeed report results.csv
158
+
159
+ # Custom output path
160
+ pagespeed report results.json -o dashboard.html
161
+
162
+ # Auto-open in browser
163
+ pagespeed report results.csv --open
164
+ ```
165
+
166
+ The HTML report includes:
167
+ - Summary cards (total URLs, average/best/worst scores)
168
+ - Color-coded score table (green/orange/red)
169
+ - Core Web Vitals pass/fail indicators
170
+ - Bar charts comparing scores across URLs
171
+ - Field data table (when available)
172
+ - Sortable columns (click headers)
173
+
174
+ ### `run` — Low-level direct access
175
+
176
+ Full control with every CLI flag. Same internals as `audit`.
177
+
178
+ ```bash
179
+ pagespeed run https://example.com --strategy desktop --categories performance accessibility --delay 2.0
180
+ ```
181
+
182
+ ## Configuration
183
+
184
+ ### Config file: `pagespeed.toml`
185
+
186
+ An optional TOML file for persistent settings and named profiles. The tool searches for it in:
187
+ 1. Current working directory (`./pagespeed.toml`)
188
+ 2. User config directory (`~/.config/pagespeed/config.toml`)
189
+
190
+ You can also pass an explicit path with `--config path/to/config.toml`.
191
+
192
+ ```toml
193
+ [settings]
194
+ api_key = "YOUR_API_KEY" # or use PAGESPEED_API_KEY env var
195
+ urls_file = "urls.txt" # default URL file for -f
196
+ delay = 1.5 # seconds between API requests
197
+ strategy = "mobile" # mobile, desktop, or both
198
+ output_format = "csv" # csv, json, or both
199
+ output_dir = "./reports" # directory for output files
200
+ workers = 4 # concurrent workers (1 = sequential)
201
+ categories = ["performance"] # Lighthouse categories
202
+ verbose = false
203
+
204
+ [profiles.quick]
205
+ strategy = "mobile"
206
+ output_format = "csv"
207
+ categories = ["performance"]
208
+
209
+ [profiles.full]
210
+ strategy = "both"
211
+ output_format = "both"
212
+ categories = ["performance", "accessibility", "best-practices", "seo"]
213
+
214
+ [profiles.core-vitals]
215
+ strategy = "both"
216
+ output_format = "csv"
217
+ categories = ["performance"]
218
+
219
+ [profiles.client-report]
220
+ urls_file = "client_urls.txt"
221
+ strategy = "both"
222
+ output_format = "both"
223
+ output_dir = "./client-reports"
224
+ categories = ["performance", "accessibility", "seo"]
225
+ ```
226
+
227
+ ### Config resolution order
228
+
229
+ Settings are merged with the following priority (highest wins):
230
+
231
+ 1. **CLI flags** — explicit command-line arguments
232
+ 2. **Profile values** — via `--profile name`
233
+ 3. **`[settings]`** — defaults from config file
234
+ 4. **Built-in defaults** — hardcoded in the script
235
+
236
+ ### Global flags
237
+
238
+ | Flag | Short | Default | Description |
239
+ |------|-------|---------|-------------|
240
+ | `--api-key` | — | config/env | Google API key |
241
+ | `--config` | `-c` | auto-discovered | Path to config TOML |
242
+ | `--profile` | `-p` | None | Named profile from config |
243
+ | `--verbose` | `-v` | False | Verbose output to stderr |
244
+ | `--version` | — | — | Print version and exit |
245
+
246
+ ### `audit` / `run` flags
247
+
248
+ | Flag | Short | Default | Description |
249
+ |------|-------|---------|-------------|
250
+ | `urls` | — | `[]` | Positional URLs |
251
+ | `--file` | `-f` | None | File with one URL per line |
252
+ | `--strategy` | `-s` | `mobile` | `mobile`, `desktop`, or `both` |
253
+ | `--output-format` | — | `csv` | `csv`, `json`, or `both` |
254
+ | `--output` | `-o` | auto-timestamped | Explicit output file path |
255
+ | `--output-dir` | — | `./reports/` | Directory for auto-named files |
256
+ | `--delay` | `-d` | `1.5` | Seconds between requests |
257
+ | `--workers` | `-w` | `4` | Concurrent workers |
258
+ | `--categories` | — | `performance` | Lighthouse categories |
259
+
260
+ ## Output Formats
261
+
262
+ ### File naming
263
+
264
+ By default, output files use UTC timestamps:
265
+
266
+ ```
267
+ {output_dir}/{YYYYMMDD}T{HHMMSS}Z-{strategy}.{ext}
268
+ ```
269
+
270
+ Examples:
271
+ ```
272
+ ./reports/20260216T143022Z-mobile.csv
273
+ ./reports/20260216T150000Z-both.json
274
+ ./reports/20260216T143022Z-report.html
275
+ ```
276
+
277
+ Use `-o` to override with an explicit path.
278
+
279
+ ### CSV
280
+
281
+ Flat table with one row per (URL, strategy) pair. Columns:
282
+
283
+ | Column | Description |
284
+ |--------|-------------|
285
+ | `url` | The analyzed URL |
286
+ | `strategy` | `mobile` or `desktop` |
287
+ | `performance_score` | 0-100 Lighthouse score |
288
+ | `lab_fcp_ms` | First Contentful Paint (ms) |
289
+ | `lab_lcp_ms` | Largest Contentful Paint (ms) |
290
+ | `lab_cls` | Cumulative Layout Shift |
291
+ | `lab_speed_index_ms` | Speed Index (ms) |
292
+ | `lab_tbt_ms` | Total Blocking Time (ms) |
293
+ | `lab_tti_ms` | Time to Interactive (ms) |
294
+ | `field_*` | Field (CrUX) metrics (when available) |
295
+ | `error` | Error message if the request failed |
296
+
297
+ ### JSON
298
+
299
+ Structured with metadata header:
300
+
301
+ ```json
302
+ {
303
+ "metadata": {
304
+ "generated_at": "2026-02-16T14:30:22+00:00",
305
+ "total_urls": 5,
306
+ "strategies": ["mobile", "desktop"],
307
+ "tool_version": "1.0.0"
308
+ },
309
+ "results": [
310
+ {
311
+ "url": "https://example.com",
312
+ "strategy": "mobile",
313
+ "performance_score": 92,
314
+ "lab_metrics": { "lab_fcp_ms": 1200, "lab_lcp_ms": 1800, ... },
315
+ "field_metrics": { "field_lcp_ms": 2100, "field_lcp_category": "FAST", ... },
316
+ "error": null
317
+ }
318
+ ]
319
+ }
320
+ ```
321
+
322
+ ## Metrics Reference
323
+
324
+ ### Lab data (synthetic, from Lighthouse)
325
+
326
+ | Metric | Good | Needs Work | Poor |
327
+ |--------|------|-----------|------|
328
+ | First Contentful Paint | < 1.8s | 1.8s–3.0s | > 3.0s |
329
+ | Largest Contentful Paint | < 2.5s | 2.5s–4.0s | > 4.0s |
330
+ | Cumulative Layout Shift | < 0.1 | 0.1–0.25 | > 0.25 |
331
+ | Total Blocking Time | < 200ms | 200ms–600ms | > 600ms |
332
+ | Speed Index | < 3.4s | 3.4s–5.8s | > 5.8s |
333
+ | Time to Interactive | < 3.8s | 3.8s–7.3s | > 7.3s |
334
+
335
+ ### Field data (real users, from CrUX)
336
+
337
+ Field data comes from the Chrome User Experience Report. It may not be available for low-traffic sites.
338
+
339
+ | Metric | Description |
340
+ |--------|-------------|
341
+ | FCP | First Contentful Paint — when first content appears |
342
+ | LCP | Largest Contentful Paint — when main content loads |
343
+ | CLS | Cumulative Layout Shift — visual stability |
344
+ | INP | Interaction to Next Paint — input responsiveness |
345
+ | FID | First Input Delay — (deprecated, replaced by INP) |
346
+ | TTFB | Time to First Byte — server response time |
347
+
348
+ ## Rate Limits
349
+
350
+ | Scenario | Limit |
351
+ |----------|-------|
352
+ | Without API key | ~25 queries/100 seconds |
353
+ | With API key | ~25,000 queries/day (400/100 seconds) |
354
+
355
+ Tips:
356
+ - Use `--delay` to increase time between requests if hitting rate limits
357
+ - Use `--workers 1` for sequential processing (safest for rate limits)
358
+ - The tool retries on 429 (rate limit) responses with exponential backoff
359
+
360
+ ## Cron usage
361
+
362
+ Output files auto-increment with timestamps, so cron jobs won't overwrite previous results:
363
+
364
+ ```bash
365
+ # Every Monday at 6am UTC
366
+ 0 6 * * 1 cd /path/to/project && pagespeed audit -f urls.txt --profile full
367
+ ```
368
+
369
+ ## Examples
370
+
371
+ The [`examples/`](examples/) folder contains ready-to-use configuration files for common workflows:
372
+
373
+ | Example | Description |
374
+ |---------|-------------|
375
+ | [`basic/`](examples/basic/) | Minimal config with API key, strategy, and a sample URL list |
376
+ | [`multi-profile/`](examples/multi-profile/) | Named profiles for quick, full, and client-report workflows |
377
+ | [`ci-budget/`](examples/ci-budget/) | Strict and lenient performance budgets for CI pipelines |
378
+ | [`sitemap-pipeline/`](examples/sitemap-pipeline/) | Sitemap auto-discovery with regex filters and section-specific profiles |
379
+
380
+ Copy any example folder into your project and edit to taste. See [`examples/README.md`](examples/README.md) for full details.
381
+
382
+ ## Testing
383
+
384
+ The project includes a comprehensive test suite (102 tests across 18 test classes). All tests run offline — API calls, sitemap fetches, and file I/O are mocked.
385
+
386
+ ```bash
387
+ # Run all tests
388
+ uv run test_pagespeed_insights_tool.py -v
389
+
390
+ # Run a single test class
391
+ uv run test_pagespeed_insights_tool.py -v TestValidateUrl
392
+
393
+ # Run a specific test method
394
+ uv run test_pagespeed_insights_tool.py -v TestExtractMetrics.test_full_extraction
395
+ ```
396
+
397
+ ## License
398
+
399
+ This project is licensed under the [MIT License](LICENSE).