A technical review of the Snack publisher network — using WrestleTalk as the worked example.
We audited WrestleTalk.com as a representative Snack publisher site. Goal: find what's holding traffic back, and propose a path that scales across publishers.
A live WrestleTalk article carries two separate, competing article schemas at once — a skeletal standalone NewsArticle block and Yoast's fuller graph typed as a generic Article, with two different types and two different date formats. Google has to guess which to trust, and neither is complete: the rich one has the weaker type, the correctly-typed one is bare. It's verifiable live in ten seconds (view-source, search NewsArticle), it's directly relevant to news/Discover eligibility, and the benchmark site emits one clean authoritative graph on an equivalent article.
Not badly built — but tooling is installed without landing, plugins fight each other, and the site fights its own architecture.
Most fixes ship in place as one mu-plugin and test results.
Structural problems only go away with a move to headless — 30 live sites, one codebase (Phase 2).
wp-file-manager (RCE history) — do this regardless of anything else.Most of the findings below stem from one structural difference. Understanding it makes the rest of the audit click.
User → BunnyCDN (10-min cache) → WordPress (PHP 8.4) renders full page
└── theme, 37 plugins, jQuery, ads — all in one app
WordPress does everything: CMS, frontend rendering, API, media, ad injection. Every plugin and theme choice directly affects what visitors download. Plugins overlap and conflict (two schema generators, two caching/optimisation layers). The CMS is publicly reachable. Caching is a bolted-on layer.
User → Cloudflare CDN (HTTP/2 + HTTP/3) → Next.js (pre-rendered pages, ISR)
↕
WordPress (private CMS — never public-facing)
↕
Dedicated media CDN (R2, WebP)
WordPress is purely an editorial backend — editors use it exactly as they always have. But visitors never touch it. Pages are pre-rendered, cached with stale-while-revalidate, and served static. The public site ships one first-party stylesheet and no render-blocking first-party JavaScript — the only other external requests are the async/deferred ad + analytics tags. Security headers, structured data, image optimisation, sitemaps — all owned by the platform, so plugins can't fight each other for control of the output.
30 publisher sites run on this stack today. Same codebase, different brands.
The priority. Foundations are decent — the execution gaps (duplicate schema, no news sitemap, no breadcrumbs, ~16k thin tag pages) are most likely holding the site back.
/news/slug/), consistent canonicalslastmod maintained)max-image-preview:large set (important for Google Discover)| Metric | WrestleTalk Article | Benchmark Article |
|---|---|---|
| Article schema | Two competing schemas | One clean NewsArticle @graph |
| BreadcrumbList schema | ❌ Missing | ✅ Present |
| Images lazy-loaded | 1 of 15 | 14 of 18 |
| Images in WebP | 0 of 15 | 12 of 18 |
| og:image | JPG, tag duplicated twice | WebP, clean |
articleSection | Leaks internal taxonomy: "App Notifications - WWE" | "News" |
| og:locale | en_US (UK publisher) | en_GB |
| Title length | Inconsistent — this one ~110 chars (truncates); others fit | Consistent ~70 chars |
| H2 structure | 5 H2s, 4 boilerplate | 3 H2s, all content |
| Head hygiene | Exposes /wp-json/ API endpoints as link tags | RSS feed declared |
The WrestleTalk article carries two separate, conflicting article schemas:
1. A standalone minimal NewsArticle block — only 7 properties, no publisher, no mainEntityOfPage, dates in +01:00 timezone. Looks hand-added or from a secondary plugin.
2. Yoast's full @graph — rich (author entity, WebPage, ImageObject, Organisation) but typed as generic Article, dates in +00:00, and missing dateModified entirely.
Two schemas, two types, two date formats — Google has to guess which to trust, and neither is complete: the rich one has the weaker type and no dateModified, the correctly-typed one is skeletal. Looks like a past schema patch that created a duplicate instead. On the benchmark there is a single authoritative graph — the platform guarantees one schema source and suppresses any competing block, so this conflict can't occur.
Verified live 29 Jul 2026 on /news/cm-punk-responds-grayson-waller-shoot-promo-wwe-nxt/: two application/ld+json blocks — a 7-property NewsArticle and a Yoast @graph typed Article with dateModified absent.
| Issue | WrestleTalk | wp-mood | Impact |
|---|---|---|---|
| News sitemap | ❌ None | ✅ Dedicated | Major for a news publisher — slower discovery of fresh content |
| Breadcrumbs | ❌ None visible, no schema | ✅ Both | Lost SERP breadcrumb display + internal linking signals |
| H1 tags | 3 on homepage | 1 | Minor — Google tolerates multiple H1s; tidy for clarity, not a likely ranking factor |
| Homepage og:image | ❌ Missing | ✅ Present | Homepage shares render without an image |
| Tag pages | ~16,000 thin pages in sitemap | Curated | Site-quality dilution at 89k-article scale (crawl budget secondary) — see below |
| RSS link | ❌ Not declared | ✅ Present | Reduced aggregator discoverability |
| PWA manifest | ❌ None | ✅ Full | Low — installability/UX, not a ranking factor |
| robots.txt | Everything open (Disallow: empty; search + wp-admin crawlable) | Selective blocking | Low-value URLs left crawlable |
| Author E-E-A-T | Thin author entities | Author pages + Person/sameAs schema | Trust signal for News/Discover |
Several of these (breadcrumbs, news sitemap) are already-installed or one-add-on-away Yoast features. Installed ≠ configured ≠ working.
In WordPress, every tag an editor attaches to a post auto-generates its own archive page and URL (e.g. /tag/roman-reigns/). WrestleTalk has accumulated ~16,000 — a figure you can read straight off the sitemap index: 16 post_tag-sitemap*.xml files at ~1,000 URLs each. Most are thin: an auto-generated list of links with no original writing, many with one or two posts, overlapping category pages and search.
Two distinct harms, in priority order:
And it isn't only tags. The sitemap index also exposes star-rating, results (×4) + results_archive, champions_category, team, tribe_events and podcast sitemaps — more auto-generated thin archives on top of the 16k tags. The fix ("Curated" on the platform): noindex the thin archives, drop them from the sitemap, keep only the genuinely useful hubs.
~89k articles (verified: 89 post-sitemap files × 1,000 URLs) + ~16k tag pages + events/quizzes = fresh articles competing with 100k+ URLs for a finite crawl budget, on top of the quality issue above. Thin archives and stale events work against discovery. The fast-indexing-api and snack-missed-schedule plugins are a tell — symptomatic fixes, installed when someone's already fighting indexing.
GET /wp-json/wp/v2/users returns HTTP 200 and leaks author names + slugs. The head also exposes /wp-json/ and the Tribe Events API. (For accuracy: xmlrpc.php is already blocked — returns 403 — so the exposure is wp-json, not xmlrpc.)X-Frame-Options, X-Content-Type-Options or Permissions-Policy; Referrer-Policy is the weak legacy no-referrer-when-downgrade.user-scalable=no, maximum-scale=1.0 — a WCAG 2.1 (1.4.4) failure, trivially fixed at the output layer.None require a rebuild — all are output-layer fixes the Phase 1 mu-plugin can own.
A platform migration doesn't mean supporting all of them — most become redundant or stay admin-side. Triage:
Caching/optimisation: w3-total-cache, perfmatters, wp-rest-cache, use-bunny-dns.
Old-frontend API auth: json-api-*, jwt-authentication.
Ad injection: ad-inserter → replaced by platform slot config.
Symptomatic fixes: fast-indexing-api, snack-missed-schedule — the platform publishes reliably and has a news sitemap.
Admin-only (zero frontend work): akismet, disable-comments, disable-gutenberg, user-role-editor, post-duplicator, post-types-order, taxonomy-terms-order, edit-author-slug, mainwp-child, wp-crontrol, wp-mail-logging, safe-svg, bdvs-password-reset.
Bounded, real work — but one-off. Each component built for WrestleTalk becomes a reusable platform capability for every subsequent publisher.
wp-file-manager — RCE vulnerability history; replace with SFTP access.
| Plugin | Frontend Need | Notes |
|---|---|---|
ninja-tables (+pro) | Table rendering component | Data via REST |
quiz-maker | Quiz component | Bounded scope |
the-events-calendar | Events listing + detail pages | Already identified |
league_wp | League/results tables | Custom plugin — needs API review |
pageviews-counter | Trending/most-read widgets | Simple |
onesignal / push-notifications | Push opt-in | Client-side SDK, standard pattern |
advanced-custom-fields-pro | Field data via API | Already supported on wp-mood |
wordpress-seo (Yoast) | Meta/schema source | Platform generates its own — Yoast becomes editorial input only |
The honest position: this is real work, but it's bounded and it's a one-off — each component built for WrestleTalk becomes a reusable platform capability for every subsequent publisher. It is not an open-ended "backward compatibility" commitment to 37 plugins.
We deliberately do not recommend jumping straight to a migration. The sequencing matters — both for risk and for proving value quickly.
Most findings don't require touching the theme or the ad stack — they're output-layer fixes. Packaged as a single deployable mu-plugin ("must-use" plugin — drops into mu-plugins/, always on, can't be deactivated or fought by other plugins)
X-Powered-By and generator meta, disable XML-RPC, restrict /wp-json/ user/plugin enumerationNewsArticle graph with BreadcrumbList, dateModified, publisher entityloading="lazy" on below-fold images via WordPress output filtersEach change measurable in Search Console and CrUX within weeks.
Honest limits: an mu-plugin can polish the output, but it's still working against the current — it can't fix render-blocking theme scripts, can't stop plugins fighting each other at the source, can't protect the origin from traffic spikes, and can't hide the CMS. That ceiling is exactly why Phase 2 exists.
For publishers where the economics justify it, migrate onto the headless stack:
This is the key to keeping the whole network aligned with Google without maintaining dozens of separate sites. Rather than a branch per site (which drift apart and become impossible to keep in sync), we run a core platform repo plus a fork per major publisher.
Scale economics: publisher #1 carries the component-building work (events, quizzes, tables) into the core; publishers #2–3 are mostly design/fork config; #4+ is primarily configuration and QA. The core gets stronger with each site.
Phase 1 de-risks Phase 2: by the time a migration decision is made, the content is clean, the schema is right, the portfolio is already benefiting — and we've proven we can deliver.
The #1 migration risk we own up-front: URL preservation. The biggest SEO danger in any platform move for an 89k-article site is breaking URLs or losing redirects. Our migration keeps the existing URL structure 1:1, carries over every legacy redirect, and diffs the live URL inventory (from the existing sitemaps) against the new build before cutover — so there is no ranking loss from the move itself. A hard commitment, not an afterthought.
With GSC access, we overlay the traffic drop against known Google update dates and segment by page type (articles / tags / Discover / News) to identify what the cliff actually was. Without it, the Phase 1 gap-closing still stands on its own — the fixes align the site with what core updates reward regardless. GSC just makes the recovery story evidence-backed rather than inferred.
The structural differences that matter for traffic.
| Metric | wrestletalk.com | wp-mood Platform |
|---|---|---|
| Architecture | Monolithic WordPress + BunnyCDN | Headless WP + Next.js ISR + Cloudflare |
| HTTP protocol | HTTP/2 | HTTP/2 + HTTP/3 |
| Compression | Brotli ✅ | Brotli ✅ |
| TTFB (cached) | ~75 ms ✅ | ~75–200 ms ✅ |
| CMS exposed | ⚠️ wp-json open (user enum); xmlrpc blocked (403) | ❌ Private |
| Article schema | 2 conflicting blocks | 1 authoritative NewsArticle @graph |
| Breadcrumbs | ❌ | ✅ |
| News sitemap | ❌ | ✅ |
| Thin tag pages | ~16k in sitemap | Curated |
| Cache strategy | 10-min CDN TTL | ISR + stale-while-revalidate |
| Origin protection | ❌ Render storm risk | ✅ Structural |
The brief for this call is simple: get traffic working again across the Snack network — starting with WrestleTalk as the pilot — without breaking anything operationally, while we scope the long-term headless move.
Phase 1 ships without touching the theme, ad stack, or editorial workflow — and rolls back instantly. The mu-plugin is additive; CDN changes are toggles; everything's measured in Search Console and CrUX. Nothing short-term puts current traffic or ad revenue at risk.
Phase 1: days-to-weeks of work, not a rebuild. The mu-plugin is a single build we deploy across the portfolio; CDN changes are configuration. First measurable wins within weeks.
So the gains are provable rather than asserted, we capture a baseline the moment we get GSC access and before Phase 1 ships:
Every Phase 1 change is then reported against that baseline in Search Console and CrUX.