SEO dashboard shows zeros after fresh install / migration
Symptom: SEO Forge → Dashboard shows “Avg score 0”, no posts in “Posts needing attention”, and your error log mentionsTable 'wp_seoforge_analysis' doesn't exist.
Cause: the analysis table didn’t get created. The activation hook normally provisions wp_seoforge_analysis on first plugin activation, but it can be skipped if the plugin was copied into wp-content/plugins/ instead of activated through the WP UI, or if a hosting migration moved the database without rerunning activation.
Fix: since 1.0.4 the dashboard renders zero-state action cards instead of crashing on the missing table — open SEO Forge → Settings → Automation → “Run bulk analysis”, which seeds the table on the first run and immediately populates the dashboard with real numbers. Alternatively, deactivate and reactivate the plugin from Plugins screen to fire the activation hook again.
Settings page looks unstyled or stops with a critical error
Symptom: SEO Forge → Settings opens with the orange product header, but the tab sidebar, cards, and Save Settings button look like plain WordPress markup, or WordPress shows a critical error before the page footer. Cause: on mixed-version Forge installs, another Forge plugin can load an older sharedForge_Connect class before SEO Forge. Older builds did not expose the Google site-token refresh helper, so SEO Forge could fatal while rendering the Integrations card. Because that happened before the footer, the late inline Settings styles/scripts were never printed.
Fix: update SEO Forge and the other Forge plugins together. Current SEO Forge checks that the shared helper exists before using it, falls back to cached license validation when needed, and ships the Settings tabs/cards/button CSS and tab JS through the normal admin assets so the page stays styled even if the inline fallback is not reached.
Bulk-fix on Site Audit times out (504 Gateway Timeout)
Cause: fixed in 1.0.3. Fix-All used to POST every failing post ID in one request. On sites with 187+ failing posts, the single request couldn’t complete within the PHP max execution time. Now the client splits the list into chunks of 5 (BULK_CHUNK = 5) and posts them sequentially.
You’ll see “Fixing 5/187…” → “Fixing 10/187…” as progress. Server also has @set_time_limit(120) + @ini_set('memory_limit','256M') safety nets so one slow OpenAI call doesn’t trip PHP’s default 30s cap.
If you still hit 504 on 1.0.3+: one of your specific posts takes >20s per AI call (unusually long content). Try fixing one post at a time to isolate which one.
Sitemap renders as raw XML tree in the browser
Cause: the XSL stylesheet reference isn’t being applied. Two checks:- File accessibility. Open
https://your-site.com/wp-content/plugins/seoforge/assets/sitemap.xsldirectly — should return XML content (text/xsl or application/xml).If 403/404, the file is missing or the host blocks .xsl. Contact host support. - Browser cache. Hard-refresh (Cmd+Shift+R / Ctrl+F5) — browsers cache XML responses aggressively.
- Security plugins/firewalls. Some WAF rules block requests to
.xslas “unusual extension”. Whitelist the URL or disable the WAF temporarily to confirm.
Google and other crawlers read the raw XML and ignore the stylesheet — the pretty view is human-only.
Length meter shows the wrong colour state
Cause: live calculation based on character count vs ideal (60 for title, 160 for description). Ranges:- 0–49% (0–29 chars for title): Short (red)
- 50–79% (30–47): OK (yellow)
- 80–100% (48–60): Ideal (green)
- >100% (>60): Long (red, “Too long — will be trimmed in Google SERP”)
If the state doesn’t match, hard-refresh — stale JS cache. Ideal lengths aren’t customisable in the UI; they’re hard-coded to current SERP norms.
Note: Google trims based on pixel width, not character count. “Ideal” in the meter = within the character budget most titles tolerate, but wide letters (M, W, capitals) can still push past Google’s pixel limit at 60 characters. If SERP still truncates, shorten regardless of the green bar.
Migration says “No supported SEO plugins detected” but I have Yoast active
Cause: fixed in 1.0.3. Detection now triggers on any of three signals:is_plugin_active(), signature wp_options (Yoast wpseo, Rank Math rank-math-options-general, AIOSEO aioseo_options, SEOPress seopress_titles_option_name), or existing postmeta rows.
Previously postmeta-only. Fresh Yoast install with no posts saved yet = zero postmeta = “not detected” even though Yoast was clearly installed.
Confirm your Yoast version: if wordpress-seo/wp-seo.php is the plugin file, activation is enough. Yoast Premium alone (without the free base) won’t register because its slug is different.
A/B Testing is locked and I can’t enable it
Cause: intentional gate. A/B testing is only useful on high-traffic pages — low-traffic sites spend weeks accumulating noise and draw wrong conclusions. To unlock:- Open any post’s SEO Forge A/B panel.
- Check “I understand this is an advanced feature and my page gets enough organic traffic for the result to be meaningful.”
- Click Unlock A/B Testing.
This flips seoforge_ab_advanced_acknowledged = 1 site-wide; all subsequent posts let you enable directly.
Server-side re-check in save_meta_box — posting to the AJAX endpoint without acknowledging won’t work either.
A/B Test running but I can’t tell which variant is live
Cause: UI shows “Week N — showing Variant A/B” and colour-coded status. If you see “Week 1 — showing Variant A” for longer than 7 days, click the post’s test start date — stored in_seoforge_ab_start postmeta. The plugin computes week number as floor((now - start) / 7 days) % 2.
If the date isn’t there, the test hasn’t actually started — save the post to initialise.
A/B Test impressions stuck at low numbers
Cause: either (a) low traffic — the feature’s minimum recommended is 2,000 impressions per variant before CTR comparison is reliable, or (b) page caching intercepts requests beforemaybe_swap_meta() runs.
Check:
SELECT meta_key, meta_value FROM wp_postmeta
WHERE post_id = <your_post_id>
AND meta_key IN ('_seoforge_ab_served_a','_seoforge_ab_served_b')If the numbers disagree strongly with your actual pageviews, a page cache is short-circuiting us. Bypass for this URL (LSCache → Do Not Cache URI / Cloudflare Cache Rules bypass) or accept the bias.
Redirects don’t fire after I add them
Cause: rules stored inwp_seoforge_redirects but handler runs on template_redirect priority 0 — some plugins run earlier and already sent a 301. Try:
- Confirm rule is
Active(not disabled) in Redirects list. - Test with an incognito window — avoid browser caching of old 301s.
- Check that no other redirect plugin (Redirection, Yoast Premium redirects, WP Rocket 404-to-homepage, security plugin) matches the same source URL first. Deactivate to isolate.
- For regex rules, test the pattern:
preg_match('/your-pattern/', $test_url)should return 1.