The Q1/Q2 2026 Sperry Tree Care campaign build covered a full-stack marketing system: 11 Kit nurture emails to ~1,400 Club members, 3 Meta paid social campaigns, WS4 Jobber-to-Kit Zapier automation, WordPress landing pages via REST API, Cloudflare Workers for all report/asset delivery, and a referral share precapture flow.
The single largest time drain was Kit API write operations being completely broken. V3 and V4 silently ignore subject and body writes, returning 200/201 while changing nothing. Multiple hours were lost diagnosing this before confirming no automation path exists. Every email body must be manually pasted via Kit UI.
The second largest issue was the Jobber to Kit automation gap: zero automation flows out of Jobber. Referred neighbors and estimate requests receive no automated follow-up. WS4 was designed to close this gap but was overdue at time of this report. This is the highest-ROI build remaining in the engagement.
On the workflow side, Meta TOS acceptance and client photo library requirements were launch blockers that should have been handled at contract signing. Approval delays cost prime spring pruning window time. These are process failures, not technology failures, and are fully preventable with updated onboarding checklists.
The patterns that emerged from this build — CF Worker as primary delivery, wrangler via Desktop Commander, navigator.share API detection, V3→V4→V3 Kit segmentation sequence, and Dispatch for unattended communication — are now locked into memory and reusable across all future client builds.
Kit V3 and V4 API POST/PUT/PATCH calls for broadcast subject, body, and from-name all return 200/201 with no error — but nothing is written. The API reports success while silently discarding the content. Only DELETE and send_at schedule writes reliably work.
Time wasted: Multiple hours across several sessions — building API calls, testing V3 vs V4 endpoints, verifying authenticated payloads, comparing request/response pairs, and ultimately confirming no automation path exists.
Setting both content and subscriber filter on a Kit broadcast requires three sequential API calls. V3 PUT sets content/from/send_at but does not preserve subscriber_filter. V4 PATCH sets subscriber_filter but wipes email_address and send_at. Correct sequence: V3 PUT → V4 PATCH → V3 PUT again to restore what V4 wiped.
The CF MCP can list workers and read configs but cannot deploy. Every CF Worker deployment requires wrangler CLI via Desktop Commander on the Mac.
cd /Users/Jason && /usr/local/bin/wrangler deploy [file] --name [name] --compatibility-date 2024-01-01 — run via Desktop Commander start_process. Reliable and fast once the pattern is known.REST API writes to _elementor_data work correctly with the BT_admin app password. But Elementor cache flush requires its own AJAX nonce — not the WP REST nonce — so app password authentication is rejected for the flush call. Every content update via headless REST requires a separate manual browser step to flush cache before changes go live.
When updating Elementor widget data via REST API with large JSON payloads (full _elementor_data structures), Wordfence WAF blocks the request. The block can appear as a 403, a timeout, or an empty response. Not immediately obvious as a WAF block vs. an API auth issue.
/wp-json/wp/v2/*). Eliminates the need to toggle WAF during every build session.Initial LP implementation set the Jobber iframe src attribute via JavaScript after page load. The iframe began loading before the script executed, causing the first load to miss the ?ref= referral parameter. Referral attribution was silently lost on a meaningful percentage of form submissions.
src="" (empty string) in HTML markup. Set the real src via JS synchronously before the browser initiates any load. Referral parameter captured correctly on every load.Initial referral share page used User-Agent string to detect mobile vs. desktop and conditionally show native share vs. Gmail/mailto fallback links. UA sniffing fails on desktop Chrome on Android, iOS Safari with desktop mode enabled, and other edge cases.
navigator.share API detection. If navigator.share exists → native share. If not → Gmail + mailto fallback. Works correctly across all devices and browser configurations.The Cowork present_files tool frequently returns "not accessible on user's computer" when attempting to deliver files from the workspace folder. No clear pattern for when it works vs. fails — appears tied to file path mapping between the Cowork sandbox mount and the Mac filesystem.
present_files is a backup-only option for non-HTML file types. Update all skill templates to reflect this default.The iMessage MCP configured with Jason's number (541-514-2521) creates a routing loop — the message routes back to the Mac iMessage app, not to the iPhone. Confirmed non-functional for all self-messaging use cases.
The Meta Marketing API MCP uses a user access token that expires (typically 60 days for long-lived tokens). No refresh token flow exists — renewal requires manually generating a new token via Meta's Graph API Explorer. Expiry is not surfaced proactively; discovered only when a call fails.
All 4 Zapier zaps in the current stack flow into Jobber (from Facebook Lead Ads and CF7 contact forms). Zero automation flows out. Every neighbor who requests an estimate after receiving a referral share gets a single Jobber confirmation email and then nothing. No follow-up sequence, no nurture, no re-engagement. WS4 was scoped to fix this but was overdue by 8+ days at the time of this report.
Because Kit API writes are broken, every broadcast email requires a full manual workflow: write HTML locally → open Kit draft URL → switch to "Custom HTML" → paste → save → verify. Attempting browser automation causes CSS artifacts. 5 min × 11 emails = ~55 minutes of manual work that should be zero-touch.
Before any Lead Gen campaign can run, the Facebook Page admin (Michele) must separately accept the Lead Ads Terms of Service at facebook.com/ads/leadgen/tos. This is a one-time step per ad account, completely independent of campaign creation — campaigns can be built and published, but they simply won't run until TOS is accepted. The dependency wasn't anticipated, causing a launch delay during peak spring season.
Initial Meta ad creative used AI-generated (Imagen 3) images as placeholders. Rob Miron rejected these and required real photos of Sperry's work before approving the campaigns. Kelly Lyons' photo library was the resolution, but sourcing the photos required additional coordination that delayed the approval cycle.
email_ws2_03.html contained two SOW violations: "priority scheduling" (prohibited per Sperry promo rules — not available and not offered) and "15% discount" (unapproved percentage discount). Caught during manual review before scheduling. Had the email been scheduled without review, two policy violations would have gone to 1,400 subscribers.
Kit broadcast stub IDs created in an earlier session (23674286–23674298) were deleted or expired by the time they were needed for scheduling. All 9 stubs had to be recreated with new IDs, and the memory file had to be updated. Cause unclear — Kit may auto-clean old unscheduled drafts, or they may have been explicitly deleted in the UI.
The Meta campaign approval page wasn't sent to Rob until April 28 — weeks after the campaigns were built. Rob held approval for 7+ days during peak spring pruning season. The campaigns were ready; the delay was a process failure in when the approval was requested, not a build problem.
Multiple compaction events occurred during long sessions. In each case, compaction triggered before _SESSION.md was updated with current state. Recovery required re-reading memory files, fetching live CF Worker pages to reconstruct the task list, and in some cases re-doing work that had already been completed but wasn't documented.
_SESSION.md after the fact, then fetching live CF Worker status pages to reconstruct actual current state. Live pages are more reliable than memory files for capturing what's done vs. pending._SESSION.md update must be a mandatory step at every milestone — after each completed task, before any complex multi-step operation. Treat it like a git commit: small, frequent, immediately after meaningful work is done.After a compaction event, the session recap prioritized recent email build work instead of addressing Jason's actual question about SOW priorities and what was still open. Required multiple corrections to re-orient. The error came from recapping what was most recent in context rather than fetching live state and answering the actual question.
_SESSION.md → (2) Fetch live CF Worker status pages → (3) Confirm Jason's current priority before any work → (4) Proceed. Never recap from memory alone after a compaction event.Session transcript JSONL files are stored at a path that doesn't map correctly to the bash sandbox mount. An attempt to read a May 4 transcript via bash returned content from an April 25 session — same filename pattern, wrong mount point.
src="" in HTML, set via JS before first load. Reliable across all browsers.cd /Users/Jason && wrangler deploy [file] --name [name] --compatibility-date 2024-01-01. Handles ES modules and service workers. CF MCP is read-only — wrangler is the only deploy path.