From Broken to Ranking: How We Rebuilt an eCommerce Cosmetics Site's Organic Presence in 90 Days
A WooCommerce store in the beauty niche. No SEO infrastructure to speak of before this engagement — broken schema, 1,454 empty alt tags, invisible analytics, and a Google Merchant Center in disarray. Here's what changed and exactly what was done.
8-week snapshot
Results after 8 weeks
11.0 → 3.8
"How to apply glitter makeup"
top 4 in 5 weeks
29.8 → 6.2
"Face glitter makeup"
page 3 → page 1
1,454 → 49
Empty alt tags
97% reduction
270
Products in GMC
fully approved with complete data
Starting point
What we inherited
The store had real products, real customers, and some organic presence — but the technical foundation was actively suppressing rankings and leaking conversions. Before writing a single piece of content, we ran a full technical audit.
Schema / Structured Data
- WooCommerce + Yoast outputting a duplicate, incomplete Product JSON-LD on every product page — missing price, availability, SKU, brand, and images
- 94 disapproved products in Google Merchant Center as a direct result
- No shipping or return policy details in schema — GSC Merchant Listings showed warnings across all 270+ products
Canonicalization
- Product URLs without trailing slashes (/product/x) competing with their canonical versions (/product/x/) — a plugin had "fixed" this by disabling WordPress's canonical redirect system entirely
- 4 products had stale Yoast canonicals pointing to old URLs — one body shimmer product generating 2,247 impressions/month was sending all link equity to a dead URL
Analytics
- A consent management plugin (CookieYes) was blocking analytics_storage: granted for every user — GA4 was recording near-zero conversion data
- No GA4 purchase event in GTM — revenue tracking didn't exist
Content & Metadata
- 1,454 product and page images had empty alt tags — 43% of all images on the site
- 41 Mardi Gras products shared identical meta descriptions, copied verbatim
- 60 blog posts had no Yoast title, meta description, or focus keyword set
- 95 product categories had no SEO metadata at all
- 84 product Yoast titles exceeded 60 characters and were being truncated in SERPs
- WordPress site name set to a keyword-stuffed string, corrupting og:site_name and Yoast title templates sitewide
Google Merchant Center
- 224 of 314 products missing shipping weight in the GMC feed
- 42 ghost/stale products from deleted slugs generating "page unavailable" disapprovals
- Two conflicting product sources (93 manually supplemented + 221 from auto-crawl) creating data conflicts and incomplete approvals
Performance
- EWWW lazy loading disabled
- LCP preload not set on the homepage hero image
- WP Rocket deferring JS in a way that introduced CLS — measured at 0.11
What we did
Fixed the technical foundation first
We don't write content for a broken site. Technical fixes came before anything else.
Custom Product Schema
Replaced WooCommerce/Yoast's incomplete output with a complete Product JSON-LD via mu-plugin: name, URL, brand, SKU, description, images (up to 10), offers with price and availability, aggregateRating, shippingDetails (US flat rate, 1–3 day handling, 3–7 day transit), and hasMerchantReturnPolicy (30-day return window). The duplicate Yoast block is stripped at wp_footer. Variable products use AggregateOffer with low/high price range.
Canonical redirect fix
Rewrote trailing slash logic as a targeted mu-plugin that 301-redirects only WooCommerce URL patterns missing the trailing slash. Deleted the plugin that had been removing WordPress's redirect system entirely.
Stale canonicals
Fixed 4 products with wrong Yoast canonical/og:url. The Aura body shimmer product (2,247 impressions/month) was sending all link equity to a non-existent URL.
Filter URL 500 errors
Price filter URLs (?min_price=, ?max_price=) were returning HTTP 500. Built a mu-plugin that 301-redirects these to clean category URLs, eliminating crawl errors.
Analytics
Removed CookieYes, restoring analytics_storage: granted for all users. Set up GA4 purchase tracking in GTM with proper Data Layer Variables for transaction ID, value, currency, and items. Revenue is now tracked.
Metadata cleanup
Unique meta descriptions written for 41 Mardi Gras products and 10 other product clusters. Yoast meta added to 60 blog posts and 75 product categories. 84 product titles shortened. WordPress site name corrected.
Alt tags
Reduced empty alt tags from 1,454 to 49 (a 97% reduction) across product images, page images, and post images.
GMC product feed
Built a custom XML feed at /product-feed.xml covering 270 published products: SKU, title, description, price + sale price, availability, images (up to 10), shipping weight, brand, shipping cost, and Google product category. Cached via transient (4 hours), auto-busts on product save. Shipping weights bulk-set via WP-CLI. Consolidated GMC to a single feed source — all 270 products fully approved.
Performance
Enabled EWWW lazy loading, added LCP preload for the homepage hero image, disabled Delay JS in WP Rocket (was causing 0.11 CLS — resolved to 0.004).
Built keyword-targeted landing pages
The site's biggest opportunity was "glitter makeup" — 22,398 impressions but sitting at position ~20. No page on the site was properly targeting it. We built five pages, each targeting a distinct keyword cluster.
| Page | Primary keyword |
|---|---|
| /glitter-makeup/ | glitter makeup |
| /halloween-glitter-makeup/ | halloween glitter makeup |
| /festival-glitter-makeup/ | festival glitter makeup |
| /glitter-lip-kit/ | glitter lip kit |
| /body-glitter/ | body glitter (existing, audited) |
Each page: full-width hero (WCAG AA contrast), 8-product bestsellers grid, feature blocks, occasion grid with internal links, FAQPage accordion with JSON-LD, and a CTA banner. H1, focus keyword, meta, and 8–13 inbound internal links for every page. The Halloween page was published in late March 2026 — deliberately 6+ months before peak Halloween traffic. It's not in the May numbers at all.
Built a content engine
Six long-form blog posts researched, written, and published between April and May 2026.
| Published | Title |
|---|---|
| Apr 6 | How to Apply Glitter Makeup for Face, Body & Hair |
| Apr 13 | How to Remove Glitter from Skin, Face & Hair |
| Apr 21 | Festival Glitter Makeup Looks for Face, Body & Hair |
| Apr 28 | Glitter Gel Makeup: What It Is and How to Use It |
| May 5 | Glitter Makeup for Beginners: What to Buy and How to Start |
| May 7 | Festival Body Glitter: The Best Products in 2026 |
Autonomous content pipeline
An autonomous content pipeline was deployed on the server (Python, runs every Monday at 9am). It pulls queries from the Google Search Console API — keywords where the site ranks below position 10 with at least 50 monthly impressions. It filters out branded terms, products the client doesn't carry, and keywords that overlap with existing landing pages. It scores candidates by intent, generates a full post via Claude API, validates it against 12 quality checks (title length, word count, block structure, FAQ format, internal links, etc.), and auto-schedules it to the WordPress queue 14+ days out. Failures trigger an email alert and a draft saved for manual review. The pipeline will continue generating and publishing posts without intervention through the rest of 2026.
Internal linking
Every new page and post was connected to the broader site.
Landing pages
All five landing pages receive internal links from: relevant product category descriptions, cross-links from other landing pages, blog post body copy, and the main /glitter-makeup/ hub page. Each landing page has 8–13 inbound internal links.
Blog posts
Each post links to relevant landing pages and product categories within the body copy. Informational posts (how-to content) funnel readers toward transactional pages.
Cannibalization fix
The homepage had been targeting "glitter makeup" — competing with the new landing page. Swapped the homepage focus keyword to "glitter cosmetics," rewrote the title to brand-level, and isolated /glitter-makeup/ as the sole target for that cluster.
May 2026 — 8 weeks post-launch
Results
Site-Wide GSC (Feb 1–Mar 10 vs Apr 13–May 10)
| Metric | Before (peak) | After (off-season) |
|---|---|---|
| Clicks | 831 | 294 |
| Impressions | 31,027 | 22,577 |
| Avg Position | 9.7 | 9.9 |
Keyword Movement
| Keyword | Position before | Position after | Imp. before | Imp. after |
|---|---|---|---|---|
| "How to apply glitter makeup" | 11.0 | 3.8 | 46 | 397 |
| "Face glitter makeup" | 29.8 | 6.2 | 4 | 446 |
| "Face glitter" | 24.4 | 9.9 | 27 | 1,442 |
| "Festival glitter makeup" | 68.4 | 14.5 | 5 | 106 |
| "Facial glitter" | 10.2 | 5.9 | 18 | 121 |
| "Face and body glitter" | 68.0 | 13.1 | — | — |
| "Glitter make up" | 10.2 | 7.1 | — | — |
| "Glitter for makeup" | 8.3 | 6.6 | — | — |
| "Glitter makeup" (primary target) | 10.4 | 10.6 | — | — |
New Keywords Now Ranking (Not Present in Baseline)
Standout wins
“How to apply glitter makeup” moved from position 11.0 to 3.8 in under 5 weeks — the blog post published April 6 is now a top-4 result. Impressions went from 46 to 397 in the same window.
“Face glitter makeup” jumped from position 29.8 (page 3) to 6.2 (page 1). Impressions up 11,000%.
“Festival glitter makeup” moved from position 68.4 (not visible) to 14.5 — a landing page published in late April, already on page 2.
Primary target — still building
“Glitter makeup” (the main keyword, 22,000+ monthly impressions) moved from 10.4 to 10.6 — still at the edge of page 1 after 8 weeks. High-volume head terms take longer. The page is indexed, cross-linked, and schema-complete. Based on the trajectory of comparable keywords on this site, page 1 is the expected outcome by summer.
What's still compounding
This case study captures 8 weeks of data. The following are still building.
- Blog posts: 6 more scheduled through June 2026. The autonomous pipeline will add another 20+ posts through October. Each post adds impressions, builds topical authority, and creates new internal linking opportunities.
- Halloween landing page: Published March 2026, 6+ months before Halloween search traffic peaks. Not in the May numbers at all. "Halloween glitter makeup" runs 2,000–6,000 searches/month with low keyword difficulty.
- "Glitter makeup" primary keyword: Still at position 10.6. Based on the trajectory of comparable keywords on this site (face glitter: 24.4 → 9.9 in 8 weeks), page 1 is the expected outcome by summer.
- GMC product feed: 270 products now fully approved with shipping weight, price, and availability data. Shopping impression increases will compound in the weeks following the next re-crawl.
Results reflect a live client engagement in the beauty niche. The store name and URL are kept private at the client's request. All metrics are sourced from Google Search Console. This page will be updated when the October 2026 data is in — Halloween season will be the real test of the early landing page strategy.
Lessons
Key takeaways
Technical debt is a ceiling, not a floor.
The site had real search presence despite its problems. Fixing the infrastructure didn't create rankings from nothing — it let existing authority flow correctly. Results appeared within weeks precisely because the content and domain had some trust; we just stopped blocking it.
Seasonal verticals need content planted early.
The Halloween landing page was built 7 months before Halloween. That's not early — that's normal. If you're waiting until August to target "halloween glitter makeup," you're competing against pages that have been indexed and linked for a year.
Autonomous publishing changes the math.
A weekly content pipeline running on the server means the content library keeps growing without ongoing intervention. By October 2026 this site will have published 30+ posts. That's a compounding asset, not a one-time project.
The boring fixes matter most.
"How to apply glitter makeup" going from position 11 to 3.8 in 5 weeks happened because the page was technically sound when it published. The highest-leverage work in this project wasn't the landing pages — it was fixing the schema, canonicals, alt tags, and metadata.
Want results like these?
This is the same approach we apply to every project.
Technical foundation first. Then content that compounds. Whether you need a new site or SEO work on what you already have — we handle both.
