WordPress & WooCommerce
Troubleshooting
Symptom-first guide for the most common WordPress plugin issues. Every fix is grounded in the actual code path โ no aspirational advice.
Widget doesn't appear on the site
Check, in order:
- Plugin configured? Open Settings โ Pitchbar. All three fields (base URL, API token, agent) must be filled. The
Enabledtoggle must be on. - Right post type? The "Post types" checkboxes gate which singular pages load the widget. By default only
post+pageare checked. WooCommerceproductpages need an explicit opt-in. - Theme calls
wp_footer()? The plugin injects the script viaadd_action('wp_footer', โฆ, 99). A theme that omitswp_footer()fromfooter.phpwon't load the widget. Most modern themes call it; legacy custom themes occasionally don't. - Caching plugin serving a stale snapshot? WP Rocket, W3 Total Cache, LiteSpeed, and Cloudflare APO can all keep a pre-widget HTML version cached for days. Flush the page cache for the affected URLs.
- Browser blocking the widget script? Open DevTools โ Network. The request to
{base_url}/widget/widget.jsshould return 200. If you seeconnect-srcviolations in the console, your CSP needs an allowlist entry. See Allowed origins.
"Test connection" fails
| Error message | Diagnosis |
|---|---|
| "Connection failed." | Network-level โ Pitchbar host unreachable from WP. Run wp shell, try wp_remote_get('https://app.pitchbar.example/up'). Common cause: outbound firewall blocking the Pitchbar host. |
| HTTP 401 invalid_token | Token plaintext is wrong (typo on paste) or the token was revoked in /settings/api-tokens. Reissue a new one. |
| HTTP 403 insufficient_ability | Token wasn't created with the wp:integration ability. Reissue with the right scope. |
| "Enter both a base URL and an API token, then try again." | One of the form fields is empty. The plugin defends client-side to avoid burning a request. |
| "Base URL must start with http:// or https://." | SettingsValidator rejects URLs without a scheme. Paste the full base URL with https://. |
| "API token format looks wrong" | Plugin expects pbar_ + 48 alphanumeric characters. Either the wrong string was pasted, or the token was truncated on copy. |
"Sync now" finishes but Pitchbar doesn't see new content
The sync POST returned successfully but the Pitchbar admin's Sources page shows no posts. Possibilities:
- Sync is still resuming. On a large site (500+ posts) the first pass only does what fits in 20s. The rest finishes on a WP-Cron tick 30 seconds later. The admin shows a soft notice: "Pitchbar is finishing a large-site sync in the background." Wait, refresh, the count climbs.
- Indexing is queued, not synchronous. Pitchbar accepts the upload and queues an
IndexDocumentJobon Horizon. On a busy worker this can run 30-60s behind. Check/admin/systemโ Failed jobs for any errors. - Vector store is provisioning. A brand-new Cloudflare Vectorize index takes about 2 minutes before queries return results. Upserts succeed immediately; reads return 0. First batch of upserts post-create can also drop silently โ re-run the sync.
- Content hash matched. If you previously synced the post and nothing changed, the response's
skipped_unchangedcount increments without re-indexing. The Document already exists; that's working as intended.
Sync resumed but never finishes
A resume transient (pitchbar_post_sync_resume or
pitchbar_product_sync_resume) sits in
wp_options but the WP-Cron continuation never
fires. Most likely:
- WP-Cron is disabled. Check
wp-config.phpfordefine('DISABLE_WP_CRON', true);. Some hosts disable it and run the cron via a real system cron โ confirm with your host. If WP-Cron is fully disabled, manually run "Sync now" again from the Settings page; the syncer reads the resume marker on its first call and picks up where it stopped. - WP-Cron is silently failing. Run
wp cron event liston the command line. Thepitchbar_run_full_sync_event/pitchbar_run_product_sync_evententries should appear with a next-run timestamp in the past.wp cron event run --due-nowforces them. - The site never receives traffic. WP-Cron is opportunistic โ it runs on the next pageview after the scheduled time. A staging site with no visitors doesn't tick the cron. Either visit any front-end page, or trigger the hook manually:
wp eval '(new \Pitchbar\Sync\PostSyncer)->runFullSync();'.
Force-clearing a stuck resume marker
If you want to start the next sync from page 1:
wp transient delete pitchbar_post_sync_resume
wp transient delete pitchbar_product_sync_resume
The next "Sync now" click then enumerates from page 1 again. Re-syncing is cheap โ Pitchbar's content_hash short-circuit avoids re-embedding unchanged posts.
Elementor / Bricks / Oxygen pages sync as empty content
Three possibilities:
- The page builder version changed its renderer signature. The plugin reflects into
\Elementor\Plugin::$instance->frontend->get_builder_content_for_display,FLBuilder::render_content_by_id, and\Bricks\Frontend::render_content. A major version that renames these returns an empty string and the plugin falls through to the vanilla path. Confirm with:wp eval '$post = get_post(YOUR_ID); echo (new \Pitchbar\Sync\PageBuilderContent)->detectBuilder($post);'. - The page genuinely is empty in the builder. Open the post in the WP admin and edit in the builder โ sometimes a migration corrupts the postmeta and the builder shows a "Default content" placeholder. Fix at the builder level; sync picks up the next save.
- You're behind a custom
pitchbar_post_content_htmlfilter. If your code returns an empty string from the filter, no content is sent. Checkfunctions.php/ mu-plugins / any custom plugin.
Coupon Apply button does nothing on the cart page
- The visitor doesn't have the
pitchbar_conv_idcookie. The widget writes it at init; check DevTools โ Application โ Cookies for the WP site origin. If absent, the widget probably never loaded on the chat page (see "Widget doesn't appear" above). - The conversation already has a different code applied. The plugin's
woocommerce_load_cart_from_sessionhook callsWC()->cart->has_discount($code)first and skips if already applied. WooCommerce only allows one of each unique code; switching codes requires removing the previous one. - The transient expired. Pending coupons live 15 minutes. If the visitor staged a code, then closed the browser for an hour before opening the cart, the transient is gone. Click Apply again in chat.
- The coupon was removed in WC admin. The plugin verifies coupon validity at apply time via
new WC_Coupon($code)->get_id(). If the code no longer maps to a coupon, the apply call returns 400invalid_coupon.
Abandoned cart trigger never fires
cart-state.jsisn't loaded. Open DevTools โ Sources, search forpitchbar-cart-state. The script only enqueues when WooCommerce is detected AND the plugin is configured.- localStorage is disabled. Private browsing, Safari ITP, or a hardened browser profile may block
localStorage.setItem. The script catches the exception silently โ there's no error UI. The trigger requires localStorage; degrade gracefully by adding a different proactive rule (e.g.timeoridle). - WC fires non-jQuery events. Some custom WC themes (Flatsome's quick-view, AJAX add-to-cart plugins) skip the standard jQuery
added_to_cartevent. The script's DOM-click fallback covers buttons with.add_to_cart_button/.single_add_to_cart_buttonclassnames โ if your theme uses different classnames, the cart state isn't recorded. Add an inline shim or open an issue. - The trigger's
idle_minutesthreshold isn't met. The widget polls every 30s and fires whennow - timestamp > idle_minutes * 60_000 ms. A 5-minute threshold means at least 5 minutes of zero cart events must elapse before the trigger considers the cart abandoned. Double-check the rule'sconditions.idle_minutes. - Global trigger cooldown. The widget enforces a 5-minute cooldown across all proactive rules so the visitor isn't ambushed at every page transition. Fire one rule, none of the others fire for 5 minutes.
HMAC verification failures (plugin REST)
Pitchbar โ plugin call returns 401 with
{ "error": { "code": "signature_mismatch" } }. The
plugin logs "Plugin REST HMAC mismatch" via
error_log when this happens. Causes, in order:
- WP server clock is more than 5 minutes off UTC. Run
date -u. Compare tohttps://time.is. If skew > 5 minutes, NTP isn't running or is broken on the host. Fix at the OS level. - Plugin's
shopper_signing_secretdoesn't match Pitchbar's. This happens if you regenerated the API token in Pitchbar (which rolls a newshopper_signing_secret) without re-running "Test connection" in WP. Re-click Test connection โ the plugin captures the new secret silently. - The signing secret is empty on the WP side. Returned as
plugin_unconfiguredrather thansignature_mismatch. Indicates the plugin was upgraded from a pre-1.1.0 install where the secret didn't exist yet. Re-click Test connection. - A reverse proxy is mutating the request body. Cloudflare's HTML rewrites, security plugins like Wordfence inline scanning, and certain mod_security rules can alter the JSON body in transit. The HMAC is computed over the raw bytes, so any mutation breaks the signature. Exclude
/wp-json/pitchbar/v1/*from rewrite/scan rules.
RTL site shows widget on the wrong edge
The plugin emits data-page-dir="rtl" and
data-page-locale on the widget script tag. The
widget reads them and mirrors the bar to the right edge of the
viewport on Arabic, Hebrew, Persian, and Urdu locales.
- Wrong locale detected? Check WP's Settings โ General โ Site Language. The plugin honours
determine_locale()(which respects per-user overrides) and falls back toget_locale(). - Custom widget skin? If you've overridden the widget's CSS via
Customize, your custom rules may not have RTL variants. Inspect.pitchbar-barin DevTools โ it should havedir="rtl"set when the page is RTL.
Plugins admin shows the "WooCommerce not detected" warning even though Woo is active
On v2.0.0+ this is impossible โ the plugin defers to
woocommerce_loaded. If you're seeing this on an
older install, upgrade to v2.0.0. Symptoms of the v1.x bug:
- Product sync button missing from Settings page.
- Coupon emission empty (no codes ever sync).
- Cart coupon REST endpoint returns 400
woocommerce_inactiveeven though Woo runs fine in/shop.
Reading plugin logs
The plugin writes to error_log via
Pitchbar\Support\Logger. To see them on a typical
WordPress install:
- Set
WP_DEBUG_LOGtotrueinwp-config.php. - The plugin's events show up in
wp-content/debug.logprefixed with[pitchbar]. - Notable lines: "Plugin REST HMAC mismatch", "PostSyncer batch failed", "CouponSyncer hydrate failed", "Lead user create failed".
Where to file an issue
If none of the above resolves your problem, open an issue with:
- Plugin version (visible at top of
wp-plugin/pitchbar/pitchbar.phpor in Plugins admin). - WordPress version + PHP version (visible in Tools โ Site Health โ Info โ WordPress).
- WooCommerce version (if applicable).
- Active page builder + its version (if applicable).
- The relevant
wp-content/debug.logtail. - A minimal reproduction: which button you clicked, what you expected, what happened.