๐Ÿšจ Emergency Fix ยท Step Diagram

Contact + Coupons HTTP 500 Fix

End-to-end recovery: 4th break of the BSP contact form. Root cause was the Apr 16 mu-plugin writer (snippet #92). This playbook walks Robert through the surgical fix with every step in order, tells Hostinger exactly what to restore, and lists the 13 safe-to-delete snippets to clean up the churn stack.

๐Ÿ—“ April 17, 2026 ยท Robert Dove ยท Dove Web Consulting ยท BSP production incident ยท Central Time

๐Ÿ•’

Incident Timeline (Central Time)

โ‰ˆ 18:00 CT Apr 17Contact + Coupons pages observed returning HTTP 500. Body = WordPress "There has been a critical error on this website."
โ‰ˆ 18:10 CTDiagnostic sweep: other pages (home, financing, services, FAQs) return 200. Only Contact + Coupons 500. All user-agents return 500 (not a UA block).
โ‰ˆ 18:20 CTRoot cause found: snippet #92 writes bsp-form-move.php to /wp-content/mu-plugins/ AND dual-registers the [bsp_contact_form] shortcode โ€” conflicting with snippet #86. Each page load triggers the fatal when the shortcode fires.
โ‰ˆ 18:30 CTRobert deletes /wp-content/mu-plugins/ entire folder via File Manager. This nukes both the bad file AND Hostinger's own hostinger-auto-update.php.
โ‰ˆ 18:45 CTRobert contacts Hostinger support requesting folder restore. Support restores folder from backup.
โ‰ˆ 19:00 CTRobert deletes snippet #92 in wp-admin. bsp-form-move.php is present on disk (restored as part of backup). 500 persists.
โ‰ˆ 19:10 CTNext action: delete bsp-form-move.php file (only โ€” leave other mu-plugin files alone). Then purge LiteSpeed + Cloudflare.
๐Ÿ”ฅ

Root Cause

Snippet #92 "BSP Create mu-plugin for form shortcode (Apr 16)" was a fix-a-fix-a-fix that wrote a mu-plugin file auto-loading before WordPress. It duplicated [bsp_contact_form] shortcode registration from snippet #86, and the mu-plugin persistence outlives the Code Snippets UI toggle. Every page containing [bsp_contact_form] (i.e. contact-us + coupons) triggered the fatal.
CONTACT FORM CHURN - 4 BREAKS DOCUMENTED IN MASTER HISTORY Mar 22 - phpMyAdmin crash wiped snippet 55 Apr 02 - snippet 55 redeployed but JS targets wrong Oxygen selector Apr 12 - form rendered after footer, 7 remote fixes failed Apr 17 - snippet 92 wrote mu-plugin, dual-registered shortcode -> 500 Pattern: each break spawns 2-3 new snippets layered on the previous broken ones. Current stack: 9 active snippets all touching one form. Architectural fix path: rebuild form as Bricks-native on bricks.callbrightside.com and retire the entire snippet stack.
๐Ÿงญ

Step-by-Step Fix

1

Delete bsp-form-move.php from disk

Do NOW

Snippet #92 already deleted โœ“. But the mu-plugin file it wrote is still on disk (Hostinger restored it as part of the folder backup). This file auto-loads before every request and triggers the 500.

Where: hPanel โ†’ File Manager โ†’ /public_html/wp-content/mu-plugins/

Delete ONLY: bsp-form-move.php

KEEP: hostinger-auto-update.php (Hostinger just restored this โ€” needed for managed updates) + any other Hostinger-managed file

Why this works now: snippet #92 is already deleted, so nothing will recreate the file after you remove it this time.

โ–ผ
2

Purge both caches

Do NOW
  • wp-admin โ†’ LiteSpeed Cache โ†’ Purge All
  • Cloudflare dashboard โ†’ Caching โ†’ Configuration โ†’ Purge Everything

Both caches persist the 500 response for ~5 min. Without purge, you'll continue to see 500 even after the file is gone.

โ–ผ
3

Verify both pages return 200

Do NOW

Open in incognito / with cache disabled:

  • https://www.callbrightside.com/contact-us/ โ†’ expect 200 OK, form renders
  • https://www.callbrightside.com/coupons/ โ†’ expect 200 OK

Test form submission. Confirm ST booking fires (snippet #82 should catch it).

If still 500 after purge: snippet #85 or #86 is the next suspect. Deactivate #85 first (JS-only mover, lowest functional impact). If still 500, carefully review #86 shortcode with Oxygen builder โ€” the page might need a different shortcode or direct [forminator_form id="290"].

โ–ผ
4

Bulk-delete 13 safe-to-remove snippets

After 500 fixed

Once the site is stable, clean the snippet churn. Select these 13 in wp-admin โ†’ Code Snippets โ†’ Bulk Actions โ†’ Delete:

โœ‚๏ธ Delete โ€” sample WP cruft (4)

  • Current year
  • Allow smilies
  • Disable admin bar
  • Make upload filenames lowercase

โœ‚๏ธ Delete โ€” TEMP / one-time tools (6)

  • Nexus Oxy Re-Sign (TEMP Apr 16)
  • Nexus Oxy Edit (TEMP Apr 16)
  • Nexus Raw Post Reader (TEMP Apr 16)
  • Nexus All Meta Dump (TEMP Apr 16)
  • Nexus Oxygen Meta Reader/Writer (Apr 16)
  • Sewer Blog File Writer (one-time)

โœ‚๏ธ Delete โ€” superseded form movers (2)

  • BSP Move Contact Form v2 (polling, Apr 16)
  • BSP Move Contact Form Above Footer (Apr 16)

โœ‚๏ธ Delete โ€” duplicate (1)

  • The second Nexus LCP + Core Web Vitals Speed Fix (you have two โ€” keep one)
โ–ผ
5

Log + document the incident

After cleanup

Log to Master History as bsp-apr17-contact-500-fix-complete (severity critical). Include:

  • Root cause: snippet #92 mu-plugin writer + dual shortcode registration
  • Actions taken: deleted #92 + bsp-form-move.php + 13 redundant snippets
  • Hostinger restore used for hostinger-auto-update.php
  • Lesson: snippets that write to mu-plugins persist beyond the Code Snippets UI โ€” never again allow a snippet to write to /wp-content/mu-plugins/ without a delete path documented

Codify the rule in CLAUDE.md: "Code Snippets may never write to mu-plugins. If a filesystem write is needed, use wp-content/plugins/ with a proper activation/deactivation lifecycle."

๐Ÿ”—

GCLID Chain โ€” DO NOT DELETE these 7 snippets

These 7 snippets are the complete GCLID attribution chain. Deleting any one breaks Google Ads offline conversion upload โ†’ Smart Bidding starves โ†’ ad CPA doubles. All 7 must stay active.
GCLID ATTRIBUTION FLOW (Ad click -> Customer -> ST job -> Google learns) [Ad Click] | v URL has ?gclid=XXXXX [Landing page] | +-- Snippet #39 "BSP GCLID Capture + Bridge Webhook" | reads ?gclid= from URL | sets nexus_gclid cookie (90-day) | POSTs initial bridge ping | +-- Snippet #49 "WP Rocket: Exclude GCLID Capture from Delay JS" prevents #39 from being lazy-loaded away (without this, script runs too late, misses the gclid param) | v [Customer fills form] | +-- Snippet #55 "BSP CRO Contact Form v4.0" (the form itself) +-- Snippet #24 "BSP Booking & Contact Form Conversion Tracker" | fires gtag conversion event +-- Snippet #22 "BSP Google Ads Global Tag" | AW-17179856077 gtag root + Conversion Linker +-- Snippet #25 "EC4L PII Bridge - Enhanced Conversions" hashes name/email/phone + sends to Google Enhanced Conversions | v [Form submitted] | +-- Snippet #53 "GCLID Bridge Sync - Nexus Pipeline" | POSTs {gclid, customer info} to VM bridge +-- Snippet #5 "Nexus GCLID Bridge Proxy" registers /wp-json/nexus/v1/gclid-bridge REST endpoint | v [VM Nexus bridge] | v maps GCLID to customer phone + stores [ST job created by tech on site] | v job has customer phone [Nexus daily upload] | v joins GCLID -> phone -> ST job -> revenue | posts to Google Ads Offline Conversions API [Google Smart Bidding] learns which GCLIDs actually produced $$$ jobs -> bids higher on similar searches next week
#SnippetRole
5Nexus GCLID Bridge ProxyRegisters /wp-json/nexus/v1/gclid-bridge REST endpoint
22BSP Google Ads Global Tag (AW-17179856077)gtag.js config + Conversion Linker
24BSP Booking & Contact Form Conversion TrackerFires ad conversion event on form submit
25EC4L PII Bridge - Enhanced ConversionsHashed PII for Google Enhanced Conversions
39BSP GCLID Capture + Bridge WebhookCaptures ?gclid= + cookies + initial bridge ping
49WP Rocket: Exclude GCLID Capture from Delay JSPrevents WP Rocket lazy-load from breaking #39
53GCLID Bridge Sync - Nexus PipelineForm-submit โ†’ VM bridge with GCLID + customer
๐Ÿ›ก๏ธ

Also Keep โ€” Contact Form + Security + Performance

โœ‹ Contact form stack

  • #55 BSP CRO Contact Form v4.0 โ€” the form
  • #73 BSP Nonce Refresh โ€” fixes cache-stale nonce
  • #82 BSP Contact Form ST Booking Fix + Slack Ashton
  • #85 BSP Move Form v3 โ€” latest form-position fix
  • #86 BSP Contact Form Shortcode โ€” Oxygen shortcode registration

โœ‹ Conversion / call tracking

  • BSP Universal Click-to-Call Conversion Tracker
  • BSP Mobile Sticky CTA Bar
  • Nexus ST Web Scheduler Widget Injection

โœ‹ Security

  • Nexus User Enumeration Protection
  • Nexus Security Headers (HSTS + XSS)

โœ‹ Performance stack

  • Nexus Speed Fix: LCP Hero Image Override
  • Nexus Speed Fix: WP Rocket Optimization
  • Nexus Speed Fix: Duplicate Preload Cleanup
  • Nexus Speed Fix: Critical CSS Inline
  • Nexus Speed Fix: JS Defer + TBT Reduction
  • BSP Render-Blocking CSS Fix (Phase 2)
  • BSP Hero Image LCP Fix (Phase 2)
  • Nexus LCP + Core Web Vitals Speed Fix (keep ONE, delete duplicate)

โœ‹ SEO / schema

  • BSP FAQ Page Schema (JSON-LD)
  • Fix: Fourth generation โ†’ 5th-generation (brand copy)
  • BSP PlumbingService Schema โ€” INACTIVE, decide whether to activate

โœ‹ Blog + UI

  • BSP Blog Archive Filter Styling
  • BSP Blog Archive Category Filter System
  • BSP Blog Archive - Show All Posts
  • BSP Blog Template v1 (Experiment #35)
  • Sewer Camera Blog CSS/JS (Post 1227)
  • Nexus Pretty Links: Duck + Quack Redirects
  • Nexus Fix: Header White Background
  • Nexus Bot Traffic Filter for GA4
  • Fix: Disable Site Kit GA4 + Consent Mode
๐ŸŽ“

Lessons Locked

Rule 1: Code Snippets may never write to /wp-content/mu-plugins/. mu-plugins auto-load and persist beyond the UI toggle. If a filesystem write is needed, use a proper plugin at /wp-content/plugins/ with an activation + deactivation hook that cleans up.
Rule 2: The contact form has now broken 4 times. Each break spawned 2-3 new snippets layered on the previous broken ones. Current stack = 9 active snippets on one form. Permanent fix: rebuild form as Bricks-native on bricks.callbrightside.com using the sewer-camera page component pattern, then retire snippets #55, #73, #82, #85, #86 entirely.
Rule 3: GCLID attribution chain (7 snippets, documented above) is the revenue backbone. No refactor, no cleanup, no snippet bulk-delete may touch those 7 without a test plan. Any "fix" that breaks the chain starves Smart Bidding โ†’ ad CPA doubles within 72 hours.
Rule 4: Every timestamp going to Hostinger support, email, or Slack uses America/Chicago, computed from actual current CT time, not a drifted internal clock.