---
type: plan
title: "Tracking, CTAs, forms and conversion"
status: draft
updated: 2026-09-02
---

# Tracking, CTAs, forms and conversion

What this plan covers: everything that turns a visitor into a measurable lead — the tags that
must survive the migration, the paired call-to-action structure, the GTM event model, the
Gravity Forms rebuild, the Typeform embed of the Business Legal Health Assessment (name to be
confirmed), cookie consent, performance measurement,
and the launch checks that prove data is flowing before the project closes. It is the build
reference for proposal week 5 ("Structured data, forms, CTAs, tracking, filtering,
performance") and the tracking half of week 6 (launch checklist).

Contract basis: the accepted proposal (sent 2026-07-30, accepted 2026-08-13), sections "Calls to
Action", "Tracking Preservation", "Contact Page and Washington-First Local Setup",
"Performance", and "Launch". The full deliverable list is in `.logs/planning/scope.md`; the
decision register and open questions are in `.logs/planning/build-plan.md`; the audit evidence
is in `notes/site-audit-2026-07.md`. This plan does not restate server or WordPress standards —
read `/srv/projects/standards/README.md` (then `wordpress.md`, `frontend.md`) before touching
`wp-content/`.

Division of labour (proposal, "How This Splits With AISV"): we build forms, CTAs, and
conversion mechanics and preserve the tags; AI Smart Ventures (AISV) owns marketing
measurement and reporting, paid, email, and CRM (Pipedrive). Coordinate with AISV directly on
anything in this plan that touches Pipedrive, the newsletter, or Hotjar; the client does not
relay between vendors.

Naming: "the assessment" below means the Business Legal Health Assessment (name to be
confirmed). Three names are in circulation (site: "Legal Health Check"; AISV deck
and the Typeform iframe title: "Business Health Assessment" / "BHA"; brand story: "Business
Legal Health Assessment"). One name everywhere is an AISV-with-client decision; the CTA labels,
event parameters, and page title in this plan take that name once it is chosen.

Google Ads is out of scope (Rian, 2026-08-24): no Ads tags, conversion imports, or account
linking in this build.

---

## Tag inventory (live site, measured 2026-09-02)

Measured from the live HTML of the home, contact, and Legal Health Check pages on 2026-09-02.
Identifiers that the 2026-09-02 ground-truth inspection also records (GTM, Google tag, GA4,
Hotjar, RB2B, Meta pixel, Usercentrics via Termageddon, Typeform widget) are confirmed; anything
marked "(page capture; re-verify at the tag audit)" comes from the page capture only and is not
in that record. Identifiers below are public in the page source; none is a secret. The RB2B snippet contains an
account key — it is not reproduced here and must not be pasted into any project file or chat;
carry it over by exporting the GTM container or copying the snippet from the live site into the
new container directly.

| Tool | Identifier | Where it loads on the live site | Owner / access status (2026-08-27) | Notes |
|---|---|---|---|---|
| Google Tag Manager | container `GTM-TGTVD37` | Hard-coded `gtm.js` snippet at the top of `<head>` on every page (no `<noscript>` iframe found — page capture; re-verify at the tag audit) | Client-owned. Access requested 2026-08-24 for rian@plusroi.com, adi@plusroi.com, plusroi@gmail.com; NOT yet granted as of 2026-08-27 — see open question 1. | Contents of the container are unknown until access is granted; assume it may hold GA4, Meta pixel, or other tags. Export it before anything else (see Preservation checklist). |
| Google tag (gtag.js) | `GT-55KZDRZS` | Hard-coded in `<head>` with `gtag("config","GT-55KZDRZS")`; the emitting plugin is to be confirmed by Rian from the exported site (Site Kit suspected: the capture references `google-site-kit` assets and a cross-domain linker for equinoxbusinesslaw.com — page capture; re-verify at the tag audit) | Managed from the GA4 admin | This is the Google tag that feeds the GA4 stream below. Because it loads outside GTM, if the GTM container also holds a GA4 configuration tag the live site has been double-counting page views (state as of 2026-09-02). Check in the container audit. |
| Google Analytics 4 | stream `G-PTGQ1K61M6`, "Equinox Website" | Via the Google tag above (the G- id does not appear in the page source) | Access granted 2026-08-27 to the three PlusROI accounts | Property is the destination for every event in this plan. |
| Google Search Console | equinoxbusinesslaw.com property | n/a (verification, not a tag) | Access granted 2026-08-27 | Needed for launch-day sitemap submission and redirect monitoring (see `.logs/planning/site-architecture.md`). |
| Hotjar | site id `3664447` | Hard-coded snippet in `<head>` (not via GTM) | Client-owned Hotjar account; account access to be confirmed (Alicia Wimmer / AISV) | AISV's deck (Phase 04) says "Reconnect Hotjar", so at least this tag is believed misconfigured. The snippet is present on the live pages; whether the account is active and recording is unverified. Proposal position: flag what we find; whether fixing it is in scope is Rian's call. |
| RB2B | reb2b snippet (account key in the snippet; not recorded here) | Hard-coded snippet in `<head>` immediately after Hotjar | Client- or AISV-owned; owner to be confirmed (AISV) | AISV Phase 02 ("route identified website visitors into Slack and Pipedrive") and Phase 03 depend on it. Must keep firing. |
| Meta pixel | present per ground truth (`connect.facebook.net`, 2026-09-02); pixel id not visible in the captured HTML | `connect.facebook.net` is referenced on every captured page; no `fbq()` init or `fbevents.js` was found in the captured HTML (page capture; re-verify at the tag audit) | AISV (paid testing, Phase 03) | Ground truth and the proposal list the pixel as live; its id and load path (hard-coded vs inside the GTM container) are confirmed from the container export. The client's 2026-08-27 instruction to remove all Facebook mentions covers links and icons, not tracking; do not drop the pixel silently — AISV decides whether it stays. |
| Cookie consent | Usercentrics via the Termageddon + Usercentrics plugin (confirmed); settings id `a64YOmRJxHylNS`, plugin v1.13.0 on live (page capture; re-verify at the tag audit) | Hard-coded Usercentrics loader in `<head>` (`uc-block.bundle.js`, `loader.js`), Termageddon custom translations, `UC_UI_SUPPRESS_CMP_DISPLAY = true`, plus the plugin's ajax script (page capture; re-verify at the tag audit) | Client-owned Termageddon subscription; licence status and login to be confirmed (Rian, week one, with Alicia Wimmer) | Must be re-attached on the new site through the plugin, not by pasting the snippet. See Cookie consent. |
| Typeform | widget `QIIINVqG`, iframe title "BHA Survey" | `embed.typeform.com/next/embed.js` on the Legal Health Check page only | Typeform account ownership to be confirmed (Rian with AISV) | The assessment itself. See The assessment. |
| Constant Contact | Active Forms signup widget script (`static.ctctcdn.com/js/signup-form-widget/...`, account id set in `_ctct_m` — not recorded here) | Loaded in `<head>` on every captured page; a `.ctct-gdpr-text` consent paragraph renders beside newsletter form 2; the visible newsletter forms are Gravity Forms (page capture; re-verify at the tag audit) | To be confirmed (Alicia Wimmer / AISV) | Suggests Constant Contact is (or was) the list behind the newsletter — inferred from the live HTML on 2026-09-02, not confirmed by the client (open question 2). See Forms. |

Rule for the new site: one GTM install (`GTM-TGTVD37`, same container, new workspace) placed
by the theme, and every other tag loaded through it — GA4, Hotjar, RB2B, the Meta pixel if
retained, and any tag AISV adds later (the deck mentions Snitcher as an RB2B alternative).
Hard-code a tag only when its vendor requires it: the Usercentrics consent loader (must run
before GTM) and the Typeform embed script (page-specific). Do not carry the live site's
hard-coded Google tag across (whichever plugin emits it); if Site Kit is wanted for Search
Console convenience, leave its Analytics module off so GA4 has exactly one load path.

## Preservation checklist

Ordered; do not start the "re-implement" steps before the audit is complete, because the
container's contents are the only record of what the live site measures as of 2026-09-02.

Before migration (needs GTM access — open question 1):

- [ ] Export the live GTM container (Admin > Export Container, the live version). Keep the JSON
      outside the project with the original emails (it carries vendor snippets and the RB2B key);
      record only its date, version number, and location in `notes/README.md`. If a redacted
      copy is wanted in `notes/`, strip the contents of every Custom HTML tag first. This is the
      rollback artefact.
- [ ] Screenshot the Tags, Triggers, and Variables lists; list every tag with its trigger in
      a table in `notes/README.md` or a linked note. Record which tags are paused.
- [ ] Note every tag that duplicates a hard-coded snippet (GA4 via the hard-coded Google tag; Hotjar;
      RB2B; Meta pixel). Decide per tag: the GTM copy becomes the only copy on the new site.
- [ ] In GA4 admin: list existing key events (conversions), custom definitions, and data
      streams. Record which events, if any, are marked as key events at audit time.
- [ ] Hotjar: confirm from the Hotjar dashboard whether site 3664447 is receiving data
      (AISV/Alicia to provide access or a screenshot). Record the finding in
      `.logs/handoff.md`; Rian decides whether repairing it is in scope.
- [ ] RB2B: confirm from the owner (AISV) that the account is active and where identified
      visitors are delivered (Slack / Pipedrive / email), so the same destination is verified
      after launch.
- [ ] Meta pixel: confirm from the container export whether a pixel exists and its id; ask
      AISV whether it stays.
- [ ] Termageddon: confirm the subscription is active and who can log in; note the Usercentrics
      settings id above and the plugin version.
- [ ] Gravity Forms: export all forms (Forms > Import/Export) and their notification and
      confirmation settings from the live site; note which forms have entries worth keeping
      (the migration route decision in `.logs/planning/content-migration.md` determines whether
      entries come across).

Re-implement on staging (https://equinoxbusinesslaw.demoing.info):

- [ ] Place the GTM snippet in `<head>` once, from the child theme
      (`wp-content/themes/kadence-child/functions.php`, a `wp_head` action ordered after the
      Usercentrics loader that the Termageddon plugin injects) or Kadence Pro's header-scripts
      element, following `/srv/projects/standards/wordpress.md`; the container id read from a
      single constant; no plugin that injects a second copy. Record the mechanism chosen in
      `.logs/handoff.md`.
- [ ] Create a new GTM workspace for the rebuild. Add the GA4 configuration tag (G-PTGQ1K61M6),
      Hotjar, RB2B, and (if retained) the Meta pixel as GTM tags, each with the consent
      settings from Cookie consent below. Remove nothing from the live version until launch —
      the live site keeps serving the published container.
- [ ] Add the event tags and triggers from Events below.
- [ ] Preview the workspace against staging with Tag Assistant; confirm every tag fires on
      the pages it should and nowhere else. Staging is behind the id-auth password gate, so
      use Tag Assistant's preview connection from a logged-in browser rather than a remote
      crawler.
- [ ] Use a GA4 filter or a staging-only lookup variable so staging hits do not pollute the
      production property (simplest: a GTM constant `env` set to `staging` in the workspace and
      a GA4 data filter on hostname; remove or flip at launch).

After launch (production domain):

- [ ] Publish the GTM workspace as a new container version, named with the launch date.
- [ ] GA4 DebugView: load home, a practice-area page, a blog post, the contact page, the
      assessment page; confirm `page_view` once per page (no duplicates) and each event from
      Events fires with its parameters.
- [ ] Tag Assistant on production: GTM, GA4, Hotjar, RB2B (and Meta) all report firing.
- [ ] Hotjar dashboard shows sessions from the new site; RB2B dashboard shows visits; Meta
      Events Manager shows activity if the pixel is retained.
- [ ] Keep verifying daily for the first week; do not close the project until the client (and
      AISV) have confirmed they see data in GA4, Hotjar, and RB2B. This is a contracted
      deliverable ("Confirmation that data is flowing correctly post-launch before we close").

## CTA structure

The pairing (AISV brand story, adopted by the proposal): **Book a Consultation** is the direct
CTA; **Take the Business Legal Health Assessment (name to be confirmed)** is the transitional
CTA, for visitors ready to engage but not to book. Both are carried together, consistently,
site-wide. This replaces the live site's single "Schedule a Meeting" ask (which links directly
to an Outlook `bookwithme` URL on every page) and the live assessment page's own "Take The
Assessment" buttons that only jump to the `#bha-form` anchor.

Placements (all in scope; proposal "Calls to Action"):

| Placement | Direct | Transitional | Notes |
|---|---|---|---|
| Persistent header CTA | Book a Consultation (primary) | Take the assessment (secondary) | Both buttons, right-aligned, both in the mobile drawer (`.logs/planning/site-architecture.md`). The assessment is also a nav entry under Our Approach, so it is one click from every page (the "front door"). Sticky behaviour is a design decision in `.logs/planning/design-direction.md`. |
| Home hero | Primary button | Secondary button | Brand story section 1 lists both. |
| Home section CTAs | As per the homepage section map in `.logs/planning/design-direction.md` (sections 1, 2, 6, 11, 12 carry CTAs) | Assessment section (brand story section 11) links to the assessment page | Every CTA in the homepage map fires an event. |
| Core pages (About, Our Approach, General Counsel, Practice Areas, A La Carte, Testimonials) | Paired CTA band near the end of the page | Same band | One reusable pattern, placed by the editor. |
| End of every blog post | Paired CTA band | Same band | Part of the single-post template, not pasted into the 513 posts (as of 2026-09-02). |
| Footer band | Paired CTA band above the footer columns | Same band | Site-wide via the footer template. |
| Assessment page | Book a Consultation appears only after the embed (do not compete with the form) | The embed itself is the CTA | See The assessment. |
| Contact page | The form is the direct path | Assessment offered below the form as the alternative | |

Build rules:

- Build the paired CTA as one unsynced Kadence pattern ("CTA band") with the two buttons'
  labels and links editable. AISV and the client must be able to drop it into any page without
  a developer.
- Every CTA button carries two stable CSS classes set in the block's Additional CSS class
  field: a path class (`cta-direct` or `cta-transitional`) and a location class
  (`cta-loc-header`, `cta-loc-hero`, `cta-loc-section`, `cta-loc-post-end`, `cta-loc-footer`,
  `cta-loc-assessment`, `cta-loc-contact`). GTM's triggers key on these classes, so renaming
  them breaks measurement; document any change here first.
- The pattern's inner blocks are declared editable (the standard in
  `/srv/projects/standards/wordpress.md`); the classes live on the pattern's button blocks so
  a placed copy inherits them.
- Direct CTA destination: the live site's booking mechanism (2026-09-02) is an Outlook `bookwithme` link
  (outlook.office.com/bookwithme/user/…@equinoxbusinesslaw.com). Whether it stays is not yet
  raised with the client (open question 4). Two encoded options:
  - If it stays: the direct CTA links out to it (new tab), and the outbound click is the
    direct-conversion event (`booking_click`). A completed booking cannot be observed from the
    site; consults are then counted in Pipedrive or Outlook, not GA4.
  - If it does not stay: the direct CTA goes to the contact page (or a dedicated consultation
    form), and `form_submit_contact` is the direct conversion.
  Do not build both; decide with Alicia Wimmer / Michelle Bomberger at the mockup review.
  **Our recommendation (Adi, 2026-09-03): the on-site form.** An outbound link is measurable
  only as a click — the booking completes on Microsoft's domain, so there is no thank-you page
  to fire a conversion on and no way to tell a click that became a booked consultation from one
  that bounced off the scheduler. `booking_click` therefore records intent and calls it a
  conversion. An on-site consultation form with its own confirmation gives a true conversion,
  carries the source field and the light qualification already sold for clean Pipedrive routing,
  and is what AISV's "Instrument the pipeline" and weekly numbers review actually need. The cost
  to the client is real and theirs to weigh: they lose Outlook's self-serve calendar picker, so
  a human replies to book the slot. Rian puts this to the client; if they keep Outlook, the
  first branch above stands unchanged and the limitation is stated plainly in the launch
  reporting so nobody reads `booking_click` as booked consultations.
- Transitional CTA destination: always the assessment page URL (see
  `.logs/planning/site-architecture.md` for the final slug), never an in-page anchor from
  another page.
- Labels are AISV copy. Until the assessment name is confirmed, use the brand story wording
  ("Take the Business Legal Health Assessment") in staging and note it as placeholder in
  `.logs/handoff.md`.

## Events

All events are pushed to the `dataLayer` and forwarded to GA4 by GTM event tags. Names are
snake_case GA4 custom events; register the parameters below as custom dimensions in GA4 (event
scope) so AISV can report on them. "Key event" is GA4's term for a conversion.

| Event | Fires when | GTM trigger | Parameters | GA4 key event |
|---|---|---|---|---|
| `cta_click_direct` | Any click on a `.cta-direct` element | Click - All Elements, matching CSS selector `.cta-direct, .cta-direct *` | `cta_location` (from the `cta-loc-*` class), `cta_label` (Click Text), `link_url`, `page_location` | No (intent, not conversion) |
| `cta_click_transitional` | Any click on a `.cta-transitional` element | Same, selector `.cta-transitional, .cta-transitional *` | Same | No |
| `booking_click` | Outbound click whose URL host is `outlook.office.com` and path contains `bookwithme` (or the replacement booking URL) | Click - Just Links, Click URL matches the booking host/path | `cta_location`, `page_location` | Yes — the direct-path conversion while the Outlook link is the booking mechanism |
| `form_submit_contact` | Gravity Forms confirmation of the contact form | Custom Event `gf_submit` pushed on the `gform_confirmation_loaded` JS event (AJAX submit), filtered on the contact form id; or the Gravity Forms confirmation page URL if AJAX is off | `form_id`, `form_name`, `need` (the "what do you need help with" selection), `page_location` | Yes — the direct-path conversion if the direct CTA routes to the form; otherwise a lead event |
| `form_submit_newsletter` | Gravity Forms confirmation of the newsletter form | Same mechanism, filtered on the newsletter form id | `form_id`, `form_name`, `page_location` | Yes (secondary lead) |
| `assessment_start` | The visitor begins the Typeform (first answer / start button) | Custom Event pushed from the Typeform Embed SDK callback (`onStarted`; fall back to `onReady` if the start callback is unavailable in the embed version used — confirm against the current Typeform embed documentation at build time) | `assessment_name`, `page_location` | No |
| `assessment_complete` | The Typeform is submitted | Custom Event pushed from the SDK `onSubmit` callback (includes Typeform's `responseId`) | `assessment_name`, `response_id`, `page_location` | Yes — the transitional-path conversion |

Why the paths are separated: AISV's Phase 01 "Weekly numbers review" tracks four numbers —
leads, consults, proposals, signed — with one owner each. The site can measure the first two
only: leads = `form_submit_contact` + `assessment_complete` (+ `form_submit_newsletter` if AISV
counts it), consults = `booking_click` (a request, not a held meeting). Proposals and signed
live in Pipedrive. Keeping direct and transitional events distinct is what lets AISV see which
door the leads came through; do not merge them into one generic `generate_lead` event even
though GA4 recommends that name — if AISV wants it, add it as an additional tag, not a
replacement.

Implementation notes:

- The Gravity Forms dataLayer push is a small snippet in the child theme (or a GTM Custom HTML
  tag) listening to `gform_confirmation_loaded` and pushing `{event: 'gf_submit', form_id,
  form_name, need}`; keep AJAX submission on so the page does not reload and the event is not
  lost. The `need` value must be the option's stable value, not its label.
- Typeform pushes come from a few lines of JS on the assessment page template that wrap
  `createWidget()` from the Embed SDK (or the `data-tf-on-*` attributes if the HTML embed is
  kept); see The assessment.
- Mark key events in the GA4 admin, not just in this table; note the date in `.logs/diary.md`.
- Test every row in GTM Preview on staging and again in GA4 DebugView on production (Launch
  verification).

## Forms

Gravity Forms is installed and active on staging as of 2026-09-02 (template clone). Which licence key it
is registered under, and whether the client's own licence transfers, is open question 8 (Rian,
week one). The proposal keeps Gravity Forms deliberately despite it being the heaviest single
retained asset; do not swap it for another form plugin to chase a performance score.

### Contact form (rebuilt)

Live form as of 2026-09-02 (form id 3 on `/contact/`): name (first/last), email, company name,
subject, message, plus a Gravity Forms honeypot; no consent text, no routing, no qualification,
no source capture. (The marketing-consent line naming "Equinox Business Law Group PLLC" belongs
to the newsletter form 2 beside it — see Newsletter subscribe form.)

New form — "light qualification" means one screen, no multi-step, nothing that makes a lawyer
enquiry feel like a survey:

| Field | Type | Required | Notes |
|---|---|---|---|
| Name | Name (first, last) | Yes | |
| Email | Email | Yes | |
| Company | Text | Yes | |
| Phone | Phone | No | Client to confirm they want it (Alicia Wimmer). |
| Company size | Drop-down | No | Bands to be confirmed with AISV; they must match how AISV qualifies in Pipedrive. Do not invent revenue bands — the deck and brand story disagree on the target size (see `.logs/planning/scope.md`, things to confirm). |
| Your role | Drop-down | No | Owner / CEO; CFO / Finance; HR; Other — mirrors AISV's Owner / CFO / HR personas so Pipedrive tagging is direct. |
| What do you need help with | Drop-down | No | Options follow the service organisation decided in `.logs/planning/site-architecture.md`; include "Fractional General Counsel" and "Not sure yet". |
| How did you hear about us | Drop-down | No | Referral; Search; LinkedIn; Newsletter; Event; Other. |
| Message | Paragraph | Yes | |
| Consent / disclaimer | HTML block + consent checkbox | Checkbox required | Disclaimer text verbatim below; entity name in the consent line per the canonical-name decision in `.logs/planning/schema-entity-plan.md` (working assumption: Equinox Business Law Group PLLC). |
| Hidden: `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content`, `referrer`, `landing_page` | Hidden | — | Dynamically populated (see Source attribution). |

Disclaimer, carried over verbatim from the live contact page (measured 2026-09-02):

> Disclaimer: Any information submitted through this contact form is not protected by
> attorney-client privilege and may be shared with third-party vendors who assist in managing
> our website. Please do not submit any overly confidential or sensitive information through
> this form. A member of our team will be in contact with you directly.

Do not edit this wording; if the client wants it changed, Michelle Bomberger approves the new
text.

### Source attribution

Leads must arrive in Pipedrive "with their source attached" (AISV Phase 01 "Clean routing";
proposal, Contact Page section). Mechanism:

- A small first-touch script (child theme, loaded on every page, a few hundred bytes) reads
  `utm_*` parameters, `document.referrer`, and the landing page path on the first page view of
  a session and stores them in a first-party cookie (30-day expiry; first touch wins, so a
  visitor who arrives from LinkedIn and submits three pages later still credits LinkedIn).
- The Gravity Forms hidden fields are populated from that cookie (Gravity Forms "Allow field to
  be populated dynamically" with the parameter name, fed by the script writing the values into
  the inputs on form render, or via the `gform_field_value_*` filter server-side reading the
  cookie).
- The same cookie feeds the Typeform hidden fields (The assessment), so both doors carry
  identical attribution.
- The cookie is functional/analytics data about the visitor's own visit; classify it in the
  Usercentrics service list so consent handling is honest (Cookie consent).

### Newsletter subscribe form

Live as of 2026-09-02: Gravity Forms forms 1 and 2 (first name, last name, email) on the home and contact
pages and a `/newsletter-sign-up/` page. The live newsletter form carries the consent line "By
submitting this form, you are consenting to receive marketing emails from Equinox Business Law
Group PLLC." (measured 2026-09-02). The live pages load the Constant Contact signup-widget
script and render a `.ctct-gdpr-text` consent paragraph beside form 2, which suggests Constant
Contact is the list (inferred from the live HTML on 2026-09-02, not confirmed by the client —
open question 2). AISV's deck calls the newsletter "In Balance" and re-introduces the general counsel offer through it in Phase 01. Which platform
receives subscribers (Constant Contact or another) and how the live forms push to it
is open question 2 (Alicia Wimmer / AISV). Build the form (name, email, consent line, honeypot)
now; wire the destination once confirmed — a Gravity Forms add-on if one exists for the
platform, otherwise the same bridge chosen for Pipedrive below.

### Spam protection

The live site uses Gravity Forms' built-in honeypot plus a separate honeypot plugin (`honeypot`
directory, WP Armour — page capture; re-verify at the tag audit). On the new site: Gravity Forms honeypot on for every form, plus a
challenge that does not add a visible widget by default — Cloudflare Turnstile (a Gravity Forms
Turnstile add-on exists in the WordPress plugin directory; the site's DNS is moving to
Cloudflare anyway) or, failing that, Google reCAPTCHA v3 through Gravity Forms' own add-on.
Decide at build time; record the choice in `.logs/handoff.md`. The site key and secret key are
entered in the Gravity Forms add-on settings in wp-admin by the person who created them (Rian
or the client), never pasted in chat or recorded in project files; verify by a test submission,
not by reading the key. Do not carry the WP Armour plugin over by reflex; add it only if spam
gets through the above.

### Notifications

- Contact form: notification to the client — recipient to be confirmed by Alicia Wimmer
  (candidate: contact@equinoxbusinesslaw.com, the general mailbox on the live site), with the
  hidden source fields included in the notification body so a human reading the email sees the
  source too. Reply-To set to the submitter.
- Newsletter form: no client notification needed unless requested; confirmation to the
  subscriber only if the platform does not send its own.
- Outbound mail from the new host: confirm with Rian how WordPress on this server sends mail
  (do not assume PHP mail from the container reaches the client's inbox); test delivery to an
  equinoxbusinesslaw.com address before launch because that domain's mail is handled by the
  client's own vendor.
- Confirmation messages: on-page confirmation (AJAX) so the `gform_confirmation_loaded` event
  fires for tracking; a redirect-to-thank-you-page confirmation is acceptable only if the
  thank-you URL is excluded from search and the GTM trigger is switched to a page-view trigger.

### Pipedrive routing

In scope: clean routing with source attribution. Out of scope (proposal, "Not included"):
anything beyond that — stages, segmentation, nurture automations, list tagging are AISV's.

How leads reach Pipedrive as of 2026-09-02, and who owns the connections, is open question 3 (AISV
with Alicia Wimmer). Choose the mechanism once that is known, in this order of preference:

1. Whatever AISV already uses — re-attach it rather than introduce a second path.
2. A Gravity Forms Pipedrive add-on (third-party; verify it maps custom fields, including the
   hidden source fields, to Pipedrive person/deal fields).
3. A Zapier or Make bridge from Gravity Forms (and from Typeform, which also has its own
   native Pipedrive integration) — one zap per form, mapping every qualification and source
   field. Credentials for the bridge are AISV's; PlusROI does not hold Pipedrive API keys.
4. Pipedrive web forms embedded in place of Gravity Forms — last resort; it forfeits the
   Gravity Forms licence, tracking hooks, and the disclaimer/consent handling above.

Whichever is chosen, the acceptance test is one: a test submission from the contact form and
one from the assessment each appear in Pipedrive with the source fields populated, within the
delay the mechanism documents.

## The assessment (Typeform)

Live state (2026-09-02, `/our-approach/legal-health-check/`): a Typeform embed —
`data-tf-widget="QIIINVqG"`, `data-tf-iframe-props="title=BHA Survey"`,
`data-tf-hidden="utm_source=,utm_medium=,utm_campaign=,utm_term=,utm_content="` (all empty),
both embed instances also set `data-tf-transitive-search-params` (one as an empty string, one
as a bare attribute — page capture; re-verify at the tag audit) — inside
`id="bha-form"`, loading `embed.typeform.com/next/embed.js`. The page's own buttons ("Take The
Assessment") link to `#bha-form`. The page frames the assessment as three pillars: Spirit /
Mind / Body. The page disclaimer says the firm "is licensed to practice law in Washington,
Idaho, and Oregon" — do not carry that sentence over unverified; the licensing wording is
Michelle Bomberger's to confirm (see `.logs/planning/build-plan.md`).

Build:

- Embed the same widget id `QIIINVqG` on the new assessment page (slug per
  `.logs/planning/site-architecture.md`). Nothing about the Typeform itself changes; rebuilding
  it as an interactive AI-driven tool (AISV Creative Concept 03, "The Smart BHA") is out of
  scope, and so is moving it to Gravity Forms.
- Prominence and path in ("front door"): the assessment gets a nav entry (under Our Approach
  per `.logs/planning/site-architecture.md`), the secondary header button, and is the
  transitional CTA target from every page; on the page the embed sits directly under a short
  intro (the brand story's "How Legally Healthy Is Your Business?" copy is the natural intro —
  AISV finalises), not behind a long page and an anchor jump. The Spirit / Mind / Body framing,
  if kept, goes below the embed or in a sidebar — design decision in
  `.logs/planning/design-direction.md`.
- Keep the five UTM hidden fields and populate them from the first-touch cookie (Forms, Source
  attribution) so attribution survives navigation between pages. Typeform's
  `data-tf-transitive-search-params` only forwards parameters present on the current page URL,
  which is not enough on its own; set the hidden values explicitly from the cookie when the
  widget is created.
- Instrument with the Embed SDK callbacks (`assessment_start`, `assessment_complete` in
  Events). Load `embed.js` only on the assessment page template.
- Load the embed in the page template (a small server-rendered block or a Kadence pattern with
  a Custom HTML block); the widget id must be editable by an admin without code so AISV can
  swap the form later — store it as a theme customizer / ACF option rather than hard-coding it
  in the template.
- Related legacy pages on the live site — `/business-health-assessment-download/`,
  `/recommendations-summary-form/`, `/recommendations-summary-download/` — may be where Typeform
  delivers results or PDFs. Whether they are still in the Typeform flow decides whether they
  migrate or redirect (`.logs/planning/site-architecture.md`); confirm with AISV before
  retiring them.
- Ownership: who owns the Typeform account, whether the plan is active, and whether responses
  already route to Pipedrive (Typeform has a native Pipedrive integration) is open question 5
  (Rian with AISV). If responses do not already reach Pipedrive, add that under Pipedrive routing.

## Cookie consent

- Re-attach Termageddon + Usercentrics through the Termageddon + Usercentrics plugin on the new
  site, connected to the client's Termageddon account (Usercentrics settings id
  `a64YOmRJxHylNS` on the live site — confirm the same policy/settings apply to the new domain
  setup). Never paste the loader snippet by hand: the live snippet's
  `UC_UI_SUPPRESS_CMP_DISPLAY = true` and translation source are plugin-managed configuration,
  and a hand-pasted copy will drift from the client's policy settings.
- Whether the policy pages (`/privacy-policy/`, `/cookie-policy/`, `/terms-of-service/`,
  `/disclaimer/`, `/eula/`) are Termageddon-generated is to be confirmed by Alicia Wimmer (with
  the licence question, open question 8); either way they migrate per
  `.logs/planning/content-migration.md`, and the cookie-policy page must stay linked from the
  consent banner's settings.
- Consent Mode: enable Google Consent Mode v2 in the GTM container (Usercentrics supports it;
  the plugin exposes the setting) with default `denied` states set before the GTM snippet
  runs, and each tag in GTM assigned its consent requirement: GA4 (`analytics_storage`), Hotjar
  (`analytics_storage`), Meta pixel (`ad_storage`, `ad_user_data`, `ad_personalization`),
  RB2B (`analytics_storage` at minimum; RB2B identifies visitors, so if it is classified as
  marketing in Termageddon's service list, follow that classification).
- Add the first-touch attribution cookie and the Gravity Forms/Typeform services to the
  Usercentrics service list through Termageddon so the policy is accurate.
- Verify: with consent refused, GA4, Hotjar, RB2B, and Meta do not set cookies or send hits
  (check in Tag Assistant and the browser's storage panel); with consent granted, all fire.
  Verify from a location where the banner is required to show, or force display through the
  plugin's test mode, because the live configuration suppresses the banner where no law
  requires it.

## Performance measurement

Contracted (proposal, "Performance"): Core Web Vitals measured on the homepage, a practice-area
page, and a blog post before launch, reported to the client as measured before-and-after
numbers. No score is promised.

Baseline on the live site — before any change to it (do this in week one, it takes an hour):

- Pages: `/`, `/practice-areas-industry/` (the only practice-area URL on the live site), and
  one blog post chosen by Adi (a representative post with a featured image; record the URL in
  `.logs/handoff.md` so the after-measurement uses the same post).
- Tool: PageSpeed Insights, mobile and desktop, three runs each; record LCP, INP, CLS, TBT, and
  the field (CrUX) values if the origin has enough traffic to show them. Save the reports
  (JSON or screenshots) under `notes/` and index them in `notes/README.md`.
- Also record the raw counts that the proposal cited so the after-numbers are comparable: on
  2026-09-02 the live home page loads 64 `<script>` tags in total and 19 stylesheets; the
  proposal's July count was 33 external scripts and 18 stylesheets (it counted external
  `<script src>` only), with 57 Search & Filter Pro asset references on a page that has no
  filter.

After — same three page types on staging before launch, and again on production after launch
(the CDN and host differ, so production is the number that goes to the client).

Build measures (all in scope):

- Conditional loading: Gravity Forms assets only on pages that contain a form (Gravity Forms
  enqueues on demand when forms are embedded via block or shortcode; do not add a global
  `gform_enqueue_scripts` call and do not style the form from the global theme stylesheet the
  way the live site does). Search & Filter Pro assets only on the blog index and archives —
  dequeue elsewhere in the child theme, or through the plugin's own option if the installed
  version offers one. Typeform `embed.js` only on the assessment page. Hotjar and RB2B load
  through GTM after consent, not in the head.
- Image optimisation across migrated media (WebP/AVIF derivatives, correctly sized images,
  `srcset`), with the hero/LCP image on each template loaded eagerly and everything below the
  fold lazy-loaded via native `loading="lazy"`. Do not bring Rocket Lazy Load across; Kadence
  and core handle it.
- Keep Beaver Builder, UABB, and PowerPack off the new site entirely; most of the live
  script/stylesheet weight is theirs.
- Report format to the client: a short table, before vs after, per page and device, plus one
  paragraph on what changed. No grades, no promises of ranking effect.

## Launch verification

Run on the production domain after DNS cut-over (Cloudflare — see
`.logs/planning/build-plan.md` for the launch sequence). Tick only when observed, not when
configured.

- [ ] GTM container version published; production pages load `GTM-TGTVD37` exactly once and
      no residual hard-coded GA/Hotjar/RB2B snippets remain in the page source.
- [ ] GA4 DebugView: `page_view` once per page on home, a practice-area page, a blog post, the
      contact page, the assessment page; hostname is the production domain.
- [ ] Each of the seven events fires with the parameters listed in Events; the key-event
      flags are set in GA4 admin.
- [ ] `booking_click` opens the booking destination in a new tab and the event is recorded
      (or, if the booking link was dropped, the direct CTA lands on the contact form).
- [ ] Contact form: test submission accepted; confirmation shown; notification received at the
      confirmed recipient with source fields in the body; entry visible in Gravity Forms; lead
      appears in Pipedrive with source fields populated. Delete the test entry/lead afterwards
      and tell AISV.
- [ ] Newsletter form: test subscription reaches the confirmed platform; test contact removed.
- [ ] Assessment: Typeform loads on the assessment page with the UTM hidden fields populated
      (check the iframe URL in devtools after arriving with a `?utm_source=test` URL on a
      different page first); test completion produces `assessment_start` and
      `assessment_complete`, a Typeform response, and (once routing exists) a Pipedrive record.
- [ ] Hotjar shows a recording from the production domain; RB2B dashboard shows the visit;
      Meta Events Manager shows the pixel (if retained).
- [ ] Consent: banner displays where required; refused consent blocks the tags; granted
      consent releases them; Consent Mode signals visible in Tag Assistant.
- [ ] Spam protection active on both forms; a submission with the honeypot filled is rejected.
- [ ] Attorney-client privilege disclaimer present on the contact form, wording unchanged.
- [ ] Every CTA button on every template carries its `cta-*` classes (spot-check header, hero,
      a section band, a post end, footer, contact, assessment).
- [ ] Before/after Core Web Vitals recorded on the three production URLs and reported to the
      client.
- [ ] No Twitter or Facebook links or icons anywhere (client decision 2026-08-27); LinkedIn and
      YouTube remain.
- [ ] Redirects, sitemap, and structured-data checks are in their own plans
      (`.logs/planning/site-architecture.md`, `.logs/planning/schema-entity-plan.md`) and run
      the same day.
- [ ] Daily re-check of GA4 real-time, Hotjar, and RB2B for seven days; client and AISV confirm
      in writing that they see data before the project is closed.

## Open questions

Numbered here; the master register with all project questions is in
`.logs/planning/build-plan.md`. Answers go to `.logs/handoff.md` and, if durable, to
`.memory/`.

| # | Question | Who confirms | Blocks |
|---|---|---|---|
| 1 | GTM access. Container `GTM-TGTVD37` not yet shared; the client's 2026-08-27 error concerns the Google tag, whose users are managed in the GA4 property admin (stream "Equinox Website"); the container is shared separately from tagmanager.google.com. Both needed for rian@plusroi.com, adi@plusroi.com, plusroi@gmail.com. | Alicia Wimmer, guided by Rian | The entire Preservation checklist; the container audit cannot start without it. |
| 2 | Newsletter platform. Which service receives "In Balance" subscribers (Constant Contact is suggested by the signup-widget script and consent paragraph in the live HTML, 2026-09-02), and how the live Gravity Forms push to it. | Alicia Wimmer / AISV | Newsletter form destination. |
| 3 | Pipedrive routing. How contact and assessment leads reach Pipedrive as of 2026-09-02, who owns the connection, and which mechanism we re-attach. | AISV with Alicia Wimmer | Forms > Pipedrive routing; the acceptance test. |
| 4 | Booking link. Does the Outlook `bookwithme` link stay behind "Book a Consultation"? Not yet raised with the client. **We recommend replacing it with an on-site consultation form + thank-you destination** (Adi, 2026-09-03; rationale in Direct CTA destination above and `notes/site-audit-2026-07.md` 4.1): an outbound link yields a click, never a confirmed booking. Raise at the mockup review call. | Alicia Wimmer / Michelle Bomberger | Direct CTA destination; whether `booking_click` or `form_submit_contact` is the direct conversion. If the form wins, it is the sold contact form with light qualification and a source field — no new scope. |
| 5 | Typeform ownership. Who owns the account, is the plan active, do responses route to Pipedrive, and are the download/summary legacy pages part of its flow. | Rian with AISV | Assessment embed continuity; legacy page disposition. |
| 6 | Hotjar state. Is site 3664447 recording; what "reconnect Hotjar" in AISV's deck refers to; is the repair in scope. | AISV reports; Rian decides scope | Whether Hotjar is "preserved" or "fixed" at launch. |
| 7 | Meta pixel. Listed as live by ground truth and the proposal, but no `fbq()` init is visible in the captured page source; what is its id, is it loaded from the GTM container, and does AISV want it kept after Facebook links are removed. | AISV (from the container export) | Tag list on the new site; consent classification. |
| 8 | Licences. Gravity Forms, Search & Filter Pro, and Termageddon — active, held by whom, transferable to the new install. | Rian, week one, with Alicia Wimmer | Forms, blog filtering, consent. |
| 9 | Notification recipient for the contact form (and whether a phone field is wanted). | Alicia Wimmer | Form notifications. |
| 10 | Entity name in the consent line ("Equinox Business Law Group PLLC" is the working assumption). | Alicia Wimmer; decided in `.logs/planning/schema-entity-plan.md` | Consent text on both forms. |
| 11 | The assessment's single name, for CTA labels, event parameter `assessment_name`, nav, and page title. | AISV with the client | Final CTA labels; until then, brand-story wording as placeholder. |
