Next: Fix C7, C9: Paste the webhook URL in Basin (Webhooks, JSON), then send a test lead from Settings or the MCP. (team)
claude "/cro-onboard Sunridge Veterinary Clinic" runs the whole playbook.The button in the Checks card. C1 to C6 read the live page and the project; C7 and C8 need a test lead.
Settings, Lead sources, Send a test lead. It proves the webhook and the identity join without a real submission.
consent.catchdigital.io/v1/consent.js in <head> on 5 of 5 pages
CRO Engine · Oct 6, 12:43 PM
phc_sunridge41230… on 5 of 5 sampled pages
CRO Engine · Oct 6, 12:43 PM
pageviews in the last 24 hours
CRO Engine · Oct 6, 12:43 PM
7.3.0 on the live page, matches the manifest
Generated for this site, so the pastes are always the current versions with this site's token. A person lands them: a PR on the repo, or custom code in Webflow.
Where: Project settings > Custom code > Head code
<script src="https://consent.catchdigital.io/v1/consent.js" defer></script>
First on any site that will get session replay or ad signals. The banner gates PostHog and tracking.js through the tg-tier contract. Run /consent-setup if the site has no catch-consent yet.
Where: Project settings > Custom code > Head code
<script>
// PostHog for Catch Website OS. Waits for the consent tier (catch-consent sets window.TG_TIER and
// TG_TIER_RESOLVED, then fires tg-tier-resolved on document with the tier string as detail). Strict
// tier: no cookies, no replay. Every input is masked in replay.
(function () {
var TOKEN = "phc_sunridge41230", HOST = "https://us.i.posthog.com";
function start(tier) {
if (window.__cdPosthogStarted) return; window.__cdPosthogStarted = true;
var strict = tier === "strict", startMs = Math.round(window.performance ? performance.now() : 0);
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once unregister opt_out_capturing opt_in_capturing get_distinct_id get_session_id identify alias reset group onFeatureFlags getFeatureFlag".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
posthog.init(TOKEN, {
api_host: HOST,
persistence: strict ? "memory" : "localStorage+cookie",
disable_session_recording: strict,
session_recording: { maskAllInputs: true, maskTextSelector: "[data-ph-mask]" },
capture_pageview: true,
autocapture: false,
// The capture check: the tier this page ran under and how long after page load PostHog started.
before_send: function (e) { if (e && e.properties) { e.properties.cd_tier = tier; e.properties.cd_start_ms = startMs; } return e; }
});
}
// A "strict" set before the tier resolves is the fail-safe, not an answer (the legacy inline tier
// snippet sets it first): wait for the event unless consent.js says it already resolved.
if (window.TG_TIER_RESOLVED || (window.TG_TIER && window.TG_TIER !== "strict")) start(window.TG_TIER);
else document.addEventListener("tg-tier-resolved", function (e) { start((e && typeof e.detail === "string" ? e.detail : null) || window.TG_TIER || "strict"); });
setTimeout(function () { if (!window.__cdPosthogStarted) start(window.TG_TIER || "strict"); }, 4000); // no consent banner on the page: strict mode
})();
</script>CRO Engine · Oct 6, 12:43 PM
input masking on; replay sampled at 10%
CRO Engine · Oct 6, 12:43 PM
appointment_requested fired on a test submit from 1 of 1 forms
CRO Engine · Oct 6, 12:43 PM
no lead has reached the ingest endpoint yet
Fix: Paste the webhook URL in Basin (Webhooks, JSON), then send a test lead from Settings or the MCP.
CRO Engine · Oct 6, 12:43 PM
that ph_distinct_id resolves to a PostHog person with sessions
no-code experiments not enabled in PostHog for this project
Fix: Turn on no-code experiments for the project and add the anti-flicker snippet. Needed before the first test, not for learning.
CRO Engine · Oct 6, 12:43 PM
1 project per site. The snippet waits for the consent tier, runs cookieless with no replay on strict, masks every input, and never changes project settings. Replay sampling and billing limits are set on the project by hand (hard rule 5).
Where: Project settings > Custom code > Footer code
<script>window.CatchDigitalConfig = { eventName: "appointment_requested" };</script>
<script src="https://consent.catchdigital.io/tracking/v7.3.0.js" defer></script>Webflow's site custom code cannot hold the 7.3.0 paste (over 20,000 characters), so Webflow sites load the version-pinned copy the consent service hosts. 7.3.0 adds ph_distinct_id, ph_session_id and event_id as hidden fields and captures the conversion in PostHog with the same event_id. When a new version ships, check C4 flags every site that is behind and this plan carries the new pinned URL.
Where: Basin: the form's Webhooks setting
https://demo.os.catchdigital.io/api/ingest/cro_live_sunridge0demo0key0000000000
Pasted by a person. Add a webhook with this URL, format JSON (original, not wrapped). Turn off the duplicate-email spam rule on forms that submit more than once per session. The same URL accepts Basin, Webflow, Typeform, HubSpot and flat JSON; the shape is detected per submission.
Where: Webflow: project settings
<style id="catch-af">body{opacity:0!important}</style>
<script>(function(){var s=document.getElementById("catch-af");function go(){if(s&&s.parentNode)s.parentNode.removeChild(s);s=null}var t=setTimeout(go,2000);function arm(){if(window.posthog&&posthog.onFeatureFlags){posthog.onFeatureFlags(function(){clearTimeout(t);go()})}else{setTimeout(arm,50)}}arm()})();</script>Paste the anti-flicker snippet into the head, after the PostHog snippet (C9 looks for it), and allow no-code experiments on the PostHog project (Experiments, New, No-code: a person turns this on once). Not needed for learning.
Installed Oct 6, 2026 via Webflow (Webflow custom code), tracking.js 7.3.0.