How to automate wordpress speed optimization with WP-CLI?
WordPress speed optimization: a data-driven, site-type playbook (WP-CLI scripts, RUM, CI/CD & ROI)
Intro — RUM-first and a 1-minute checklist
Start with real users. If you don’t know which pages are losing people, you’re guessing. Want to stop guessing?
One-minute checklist you can run right now:
- Capture field LCP, CLS and INP with the web-vitals library and GA4. (Snippet below.)
- Run Lighthouse CLI on three high-traffic pages in staging.
- Clear transients and regenerate thumbnails with WP-CLI (commands below).
- Turn on a CDN with HTML caching or edge fragments for dynamic pages.
- Start a Lighthouse CI job to block regressions on PRs (example YAML later).
Why this guide?
Here’s the deal: I think teams waste time fixing the homepage while the cart page quietly drives losses. Sound familiar? I’ve seen it a dozen times.
So this guide focuses on the pages that actually matter — with playbooks for blog, brochure, WooCommerce, membership, and SaaS sites. Copy/paste-ready scripts for staging included. Want a free staging audit and a 30-minute consult from Pixel Hover? Skip to the CTA at the end.
How to use this guide — quick rules
Pick the playbook for your site type and paste the scripts into staging. Don’t run things on production without a backup. Seriously — snapshot or dump first.
When you run WP-CLI on staging:
- Run it from the site root.
- Export the DB first: wp db export /tmp/site-backup.sql
- Use dry-run or test flags where available.
Quick glossary
- LCP: Largest Contentful Paint — when main content appears.
- CLS: Cumulative Layout Shift — unexpected layout jumpiness.
- FID/INP: First Input Delay / Interaction to Next Paint — how responsive the site feels.
- TTFB: Time To First Byte — server response time.
- RUM: Real User Monitoring — metrics from real visitors.
- CrUX: Chrome User Experience Report — public RUM aggregate.
- WP-CLI: WordPress Command Line Interface.
- Lighthouse CI: automate Lighthouse runs in CI/CD.
Step 1 — Establish a baseline: RUM + synthetic tests
Look — if you start optimizing without field data you’re wasting time and money. Collect RUM and synthetic metrics in parallel. Which pages get the most traffic? Which ones have the worst LCP? Those are your targets.
Collect RUM (web-vitals + GA4)
Add the web-vitals library and send metrics to GA4 via gtag. Want the snippet? Here it is:
“`html
“`
Export CrUX and PSI data
Pull PageSpeed Insights API data (or CrUX BigQuery if you have it) to combine lab and field metrics. Weight pages by sessions so you’re not optimizing rare edge cases. Multiply sessions by poor LCP and sort. Want to know which pages matter? Do that math.
Example GA4-ish BigQuery to find pages with worst LCP weighted by sessions:
“`sql
SELECT
page_path,
COUNT(*) AS sessions,
AVG(event_value) AS avg_LCP
FROM `events_intrinsics_table`
WHERE event_name=’web_vitals’ AND metric=’LCP’
GROUP BY page_path
ORDER BY sessions * avg_LCP DESC
LIMIT 50;
“`
Run Lighthouse/PSI lab tests
Run Lighthouse CLI on representative pages:
“`bash
lighthouse https://example.com/page –output=json –output-path=./report.json –emulated-form-factor=mobile –throttling-method=provided
“`
Combine lists
Make a single priority list: pages sorted by (sessions * LCP_penalty). That’s your roadmap. Simple. Effective.
Recommended thresholds (quick targets)
- LCP < 2.5s good; aim <2s for commerce.
- CLS < 0.1.
- INP < 200ms.
- TTFB < 200–500ms (host dependent).
Step 2 — Define goals and budgets (global + site-type)
Set budgets that map to revenue. E-commerce needs tighter LCP targets than a brochure site. Why? Faster checkout pages mean fewer abandoned carts. Makes sense, right?
Sample budgets by site type
- Blog: LCP < 2.5s, CLS < 0.1, TTFB < 600ms
- Brochure: LCP < 2.2s, CLS < 0.1, TTFB < 400ms
- WooCommerce (catalog/product): LCP < 2.0s, checkout flows LCP < 1.8s, TTFB < 300ms
- Membership/LMS: authenticated areas LCP < 2.0s
Lighthouse budget example (budget.json)
“`json
{
“resourceSizes”: [{ “resourceType”: “script”, “budget”: 150 }],
“resourceCounts”: [{ “resourceType”: “third-party”, “budget”: 5 }],
“timings”: [{ “metric”: “largest-contentful-paint”, “budget”: 2500 }]
}
“`
Map to ROI
Want proof it’s worth doing? Estimate conversion uplift from LCP improvements. Example: checkout conversion is 2% and LCP drops from 4s to 2s — expect a low single-digit percent uplift. Use your AOV and traffic to calculate monthly revenue impact. Do the math. It’s straightforward.
Site-type playbooks — quick overview
I like to sort fixes into Immediate (low effort, high impact), High, Medium, Low. For each fix I estimate impact and hours. Pick the playbook that matches your site and start with Immediate items.
Blog site playbook — priority list + commands
Immediate
- Automate WebP/AVIF conversion and serve via srcset. Impact: LCP -0.5–1.5s. Effort: 2–8h.
- Enable aggressive CDN cache for HTML and images (cache-first for static pages). Impact: LCP -0.5s. Effort: 1–2h.
- Defer third-party embeds (YouTube, social). Impact: LCP -0.3–0.8s. Effort: 1–4h.
High
- Generate critical CSS and inline above-the-fold rules. Impact: LCP -0.2–0.6s. Effort: 4–8h.
- Remove unused plugins and theme features. Impact: variable. Effort: 2–6h.
WP-CLI and shell snippets for blogs
Backup first:
“`bash
wp db export /tmp/site-backup.sql
“`
Clean revisions and transients:
“`bash
wp post delete $(wp post list –post_type=’revision’ –format=ids) –defer-term-counting
wp transient delete –all
“`
Regenerate thumbnails (staging):
“`bash
wp media regenerate –yes –image_size=full
“`
Bulk convert existing images to WebP (test on staging first)
“`bash
do not run on production without testing
find wp-content/uploads -type f -iname ‘.jpg’ -o -iname ‘.jpeg’ -o -iname ‘*.png’ | while read img; do
webp=”${img%.*}.webp”
cwebp -q 80 “$img” -o “$webp” && echo “Converted $img”
done
“`
Then use a rewrite or plugin to serve .webp when available.
How to speed up WordPress on shared hosting?
You can’t tune everything on shared hosts. So pick the wins that actually move the needle:
- Use a page-caching plugin that plays nice with your host. Watch HTML minify conflicts.
- Offload images to a CDN.
- Increase PHP-FPM workers if your host allows.
- Turn on object cache (Redis/memcached) if offered.
What’s your host blocking you from doing?
Brochure site playbook — quick wins + commands
Immediate
- Edge HTML caching at the CDN (long TTLs for anonymous visitors). Impact: LCP -0.3–1.0s. Effort: 1–3h.
- Add Cache-Control and Surrogate-Control headers.
- Remove unused JS/CSS and inline critical CSS.
Cache-Control examples
- Static assets: Cache-Control: public, max-age=31536000, immutable
- HTML (anonymous): Cache-Control: public, max-age=60, stale-while-revalidate=3600
- Authenticated/dynamic: Cache-Control: private, max-age=0, no-cache
Purge rules
Cloudflare: purge by cache-tag or URL patterns on deploy. Fastly/CloudFront: use surrogate-control/cache-tags and purge API during CI. Easy to automate.
Best CDN config for dynamic WordPress pages
Use cache tags and edge fragments for dynamic widgets (cart counters, login badges). For simple brochure sites, full HTML caching at the edge with short TTLs and quick invalidation works great.
WooCommerce playbook — cart, checkout, sessions, queries
This one matters. Slow checkout kills conversions. Want to know where to start?
Core ideas
- Cache product pages aggressively but exclude cart/checkout. Use ESI for personalized bits like cart count.
- Use Redis for sessions and WooCommerce transients.
- Index product meta queries (wp_postmeta) used for filtering.
- Find slow queries and add indexes or move heavy meta lookups into a custom table.
WP-CLI & SQL to find big tables and transient bloat
Find big tables:
“`bash
wp db query “SELECT table_schema AS db, table_name AS tbl, ROUND(((data_length + index_length) / 1024 / 1024),2) AS size_mb FROM information_schema.TABLES WHERE table_schema = DATABASE() ORDER BY (data_length + index_length) DESC LIMIT 20;”
“`
Find transients in options:
“`bash
wp db query “SELECT option_name, LENGTH(option_value) AS size FROM wp_options WHERE option_name LIKE ‘\_transient\_%’ ORDER BY size DESC LIMIT 50;”
“`
Clean expired transients:
“`bash
wp transient delete –all
“`
Reduce TTFB on nginx/Apache
- Turn on PHP-FPM and tune pm.* settings for worker counts.
- Use OPcache and preloading if your PHP supports it.
- Use a persistent object cache (Redis) and store sessions on a fast backend.
- Add gzip or brotli compression and proper Expires headers.
Flush Redis (only if you know what you’re doing)
“`bash
context: only if you’re certain
redis-cli -h 127.0.0.1 -p 6379 FLUSHDB
“`
Membership & LMS playbook — sessions and personalization
Segregate authenticated content. Cache public content aggressively and only fragment the personalized parts. Sounds obvious, but many sites cache everything and break logged-in experiences.
Recommendations
- Store sessions in Redis with short TTLs.
- Move heavy ops (certificate checks, course progress recalculation) to background jobs.
- Use object cache and cache tags to invalidate only what’s needed.
SaaS/product site playbook — APIs, client-side, SSR
API latency often controls LCP for API-driven pages. So what can you do?
Tactics
- Preconnect and preload key API domains.
- Reduce server-rendered payload by sending minimal HTML and hydrating only critical components.
- If you use SSR, consider small compute at the edge to cut origin TTFB.
WP-CLI & automation-first toolkit — exact commands
DB cleanup and optimization
“`bash
export
wp db export /tmp/site-backup-$(date +%F).sql
delete revisions
wp post delete $(wp post list –post_type=’revision’ –format=ids) –defer-term-counting
optimize tables
wp db query “OPTIMIZE TABLE wp_postmeta, wp_posts, wp_options;”
“`
Flush object cache (Redis)
“`bash
clear all keys in the Redis DB used by WP
redis-cli -h 127.0.0.1 -p 6379 FLUSHDB
“`
Regenerate images
“`bash
wp media regenerate –only-missing –yes
“`
Find potentially slow plugins (quick audit)
“`bash
list active plugins and versions for a quick check
wp plugin list –status=active –format=json | jq -r ‘.[] | “\(.name) \(.version)”‘
“`
Bulk WebP conversion script
“`bash
#!/bin/bash
set -euo pipefail
UPLOADS=”wp-content/uploads”
find “$UPLOADS” -type f \( -iname ‘.jpg’ -o -iname ‘.jpeg’ -o -iname ‘*.png’ \) | while read -r img; do
webp=”${img%.*}.webp”
if [ ! -f “$webp” ]; then
cwebp -q 80 “$img” -o “$webp” && echo “Converted $img -> $webp”
fi
done
“`
Optionally import converted files into WP:
“`bash
find wp-content/uploads -type f -iname ‘*.webp’ | while read -r f; do
wp media import “$f” –skip-copy –title=”$(basename “$f”)” –porcelain
done
“`
Images & media automation — WebP/AVIF, srcset, lazy-loading
Server-side conversion options
- Use an image-optimizer CI step (sharp or imagemin) to create WebP/AVIF on upload and push to a CDN bucket. Or use a plugin that generates WebP on demand. Which path? It depends on traffic and build complexity.
srcset and responsive images
WordPress outputs srcset natively. Make sure your theme doesn’t strip width attributes or wrap images in markup that removes srcset.
Lazy-loading and SEO
Use native loading=”lazy”. But give noscript fallbacks for critical SEO images. And for above-the-fold hero images, don’t lazy-load. They need to show fast.
Example imagemin pipeline (CI)
- Use sharp or imagemin in a CI job to create multiple sizes and AVIF/WebP outputs, push to uploads or a CDN bucket, and update attachment metadata via WP-CLI or the REST API.
Caching & CDN config — headers, purge rules, edge caching
Header examples
- Static assets: Cache-Control: public, max-age=31536000, immutable
- Public HTML: Cache-Control: public, max-age=60, stale-while-revalidate=86400
Surrogate-Control: max-age=3600
- Dynamic/auth pages: Cache-Control: private, max-age=0, no-cache, must-revalidate
Purge and invalidation workflow
Tag content updates with cache-tags or surrogate keys (post:123). Trigger purge from deploy hooks:
“`bash
curl -XPOST “https://api.cdn/purge” -d ‘{“tag”:”post-123″}’
“`
Hook this into save_post or publish_post with a tiny plugin or a WP-CLI hook.
Edge caching dynamic pages
Edge-side includes (ESI) let you cache most of a page and fetch small personalized fragments on each request. Great for cart counters and login badges. Available in Fastly, some CDNs, and via Cloudflare Workers or edge functions.
Database & backend tuning — indexes, transients, TTFB
Slow queries often come from meta queries and oversized options. Find them and fix them.
Find slow queries
Enable MySQL slow_query_log or use Query Monitor in staging. Quick test:
“`sql
EXPLAIN SELECT * FROM wp_postmeta WHERE meta_key = ‘_price’ AND meta_value > 0;
“`
Add indexes where helpful:
“`sql
ALTER TABLE wp_postmeta ADD INDEX idx_meta_key (meta_key(191));
“`
Tidy options and transients
Inspect oversized options:
“`bash
wp db query “SELECT option_name, LENGTH(option_value) AS size FROM wp_options ORDER BY size DESC LIMIT 30;”
“`
Move large serialized options into a custom table when necessary.
Tuning PHP-FPM and MySQL
- PHP-FPM: tune pm.max_children to match memory and concurrency.
- MySQL: set innodb_buffer_pool_size to ~60–75% of available RAM on a dedicated DB host.
Diagnosing plugin & theme bottlenecks
Install Query Monitor on staging and reproduce slow requests. Use Xdebug or Blackfire for deeper traces. Want a fast isolation trick? Deactivate half the plugins and test. Binary search until you find the offender.
Example quick disable:
“`bash
wp plugin deactivate plugin-slug
or in bulk:
wp plugin deactivate $(wp plugin list –status=active –field=name | grep ‘suspicious-plugin’)
“`
Mobile-first performance — critical CSS, conditional loading, fonts
Extract critical CSS for the homepage and key landing pages with the npm critical package:
“`bash
npx critical https://example.com –minify –inline
“`
Preload the primary font, use font-display: swap, and subset fonts where possible. Fonts can block paint. Fix them.
How to fix LCP in WordPress
- Reduce server response time (TTFB).
- Optimize and serve the hero image (WebP/AVIF, responsive sizes).
- Inline critical CSS for above-the-fold.
- Defer non-critical JS and third-party scripts.
Before-and-after benchmarks — make them reproducible
Document the environment: host, PHP version, PHP-FPM settings, active plugins, CDN. Use Lighthouse CLI with consistent flags:
“`bash
lighthouse https://staging.example.com –preset=desktop –output=json –output-path=./lh-desktop.json –throttling-method=simulate
“`
Record seed metrics (LCP, CLS, INP, TTFB). After changes, rerun the same commands and note deltas. Publish anonymized CSVs. Want stakeholders to believe the numbers? Show the baseline, the change, and the environment.
Integrate performance testing into CI/CD (Lighthouse CI)
Sample GitHub Actions job (simplified):
“`yaml
name: lighthouse-ci
on: [pull_request]
jobs:
lhci:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– uses: chromaui/action-lighthouse@v8
with:
urls: ‘https://staging.example.com’
configPath: ./lighthouse-ci-config.json
assert: ‘{“assertions”:{“largest-contentful-paint”:”error”}}’
“`
Lighthouse CI config (lighthouserc.json)
“`json
{
“ci”: {
“collect”: { “url”: [“https://staging.example.com”], “numberOfRuns”: 3 },
“assert”: { “assertions”: { “lighthouse:performance”: [“error”, { “minScore”: 0.9 }] } }
}
}
“`
Block merges on failing thresholds. Want to keep regressions out of main? This helps.
Cost vs impact matrix and an ROI example
Score each change 0–10 for effort and impact. Plot a 2×2: low effort/high impact fixes go first. Need an example? Image automation usually takes one dev day and can shave 0.5–1.2s off LCP on image-heavy pages.
Worked example: image automation
- Effort: ~8 hours dev + CI job.
- Expected impact: LCP -0.5 to -1.2s on image-heavy pages.
- Conversion uplift: 5–15% on article pages for some sites.
Do the math: monthly visits conversion rate AOV * uplift% = revenue uplift.
Operationalizing improvements — runbook, monitoring, alerts
Set alerts:
- RUM: watch 7-day 95th percentile LCP; alert when > 2.5s.
- Synthetic: Lighthouse CI failures => notify Slack and block deploys.
- Uptime and critical flow tests (checkout): daily synthetic checks.
Tools we recommend
- SpeedCurve, Calibre for combined synthetic + RUM dashboards.
- New Relic or Blackfire for server-side profiling.
- Sentry for tracing JS errors.
30/60/90 day tactical plan and checklist
30 days
- Set up RUM and Lighthouse CI.
- Clean transients and regenerate images on staging.
- Implement CDN and base cache rules.
60 days
- Automate the image pipeline.
- Add object cache (Redis).
- Optimize DB and add necessary indexes.
90 days
- Implement edge fragments/ESI for personalization.
- Fully integrate Lighthouse checks into CI.
- Run an A/B test for checkout speed improvements.
Troubleshooting cheat-sheet & escalation playbook
Quick steps to isolate regressions:
1. Reproduce on staging.
2. Disable caching (wp cache flush; disable CDN) to compare origin behavior.
3. Binary search plugins: deactivate half, test, repeat.
4. Run Query Monitor and check PHP-FPM/NGINX logs.
5. If origin TTFB is high, open a host ticket with traces and timing data.
Useful quick commands
“`bash
disable all plugins except must-haves
wp plugin deactivate $(wp plugin list –status=active –field=name | grep -v ‘woocommerce\|your-essential-plugin’)
enable debug logging
wp config set WP_DEBUG true –raw
wp config set WP_DEBUG_LOG true –raw
“`
Pixel Hover toolkit — what to include
If you bundle this into a toolkit, include:
- WP-CLI scripts (DB cleanup, cache priming)
- Bash image conversion scripts
- Lighthouse CI config + example GitHub Actions YAML
- Performance budget spreadsheet and ROI calculator
- Case study template and benchmark CSV
Docs and references
- PageSpeed Insights: https://developers.google.com/speed/pagespeed/insights/
- WP-CLI: https://wp-cli.org/
- Lighthouse CI: https://github.com/GoogleChrome/lighthouse-ci
Want to deep-dive?
Fork the repo in the toolkit, run the staging scripts, and test everything. Test first. Then deploy.
Next steps and CTA
Want Pixel Hover to run a free staging scan and a 30-minute consult? We’ll capture RUM, run a Lighthouse baseline, and hand you a prioritized action list. Book a free strategy call today. We also run managed performance packages for WooCommerce and complex sites. Want the toolkit now? Download it and copy the scripts into staging before touching production.
Need help picking the right next step?
Send us the top three URLs on your site that drive the most traffic or conversions, and we’ll prioritize fixes you can test in a week.
Internal links (for Pixel Hover)
- WordPress development services: /services/wordpress-development
- WooCommerce services: /services/woocommerce
- Lighthouse CI guide: /blog/lighthouse-ci-wordpress
- WP-CLI recipes: /tools/wp-cli-recipes
- Performance packages and pricing: /pricing/performance-packages
Done reading? Good. Which three pages should we look at first?