Skip to content

GoHighLevel

Form Embed Swap (Source CMS → GHL)

Platform
GoHighLevel
Owner
GoHighLevel Specialist
Assignee
Anne
Supports
Website Specialist, CSM
Needs review — This SOP contains our content but has not been verified by Nick. Treat as a working draft until marked Live.

Last Updated: 2026-05-01 Version: 1.0 Tier: Cutover prerequisite


Source-CMS forms (Squarespace forms, WordPress contact plugins, GHL native forms on the source site) don’t work cross-domain. Their submit endpoints are tied to the source CMS account and either fail silently or post submissions to the wrong place after cutover.

The fix: replace every form on every cloned site with a GoHighLevel embed that posts directly to the appropriate GHL location. Same fields, same visual layout, different backend.

This SOP walks through how to swap each form type.

When to Use:

  • During the visual diff phase — document every form
  • Before scheduling a cutover — every form must be swapped first
  • When a client adds a new form post-cutover

Owner: Web Designer (executes), CSM (confirms which GHL location each form routes to) Timeline: ~10 minutes per form once you have the GHL embed code.


flowchart TD
Diff[Visual diff finds<br/>every form on the site] --> Inventory[Document each form:<br/>page, fields, GHL target]
Inventory --> CSM{CSM confirms<br/>GHL location for each}
CSM --> Embed[Get GHL embed code<br/>per form/location pair]
Embed --> Swap[Replace form HTML<br/>in src/data/&lt;page&gt;.body.html]
Swap --> Test[Submit test entry<br/>verify in GHL]
Test --> Done([All forms wired<br/>ready for cutover])
style CSM fill:#fbbf24,color:#000
style Test fill:#fbbf24,color:#000
style Done fill:#22c55e,color:#fff

Most client sites have one or more of these. Each has a slightly different swap pattern.

Standard fields: Name, Email, Phone, Message. Sometimes a “How did you hear about us” dropdown.

GHL location target: the client’s primary “Contact / General Inquiries” pipeline.

Fields: Name, Email, Phone, Service, Project description, Sometimes budget.

GHL location target: “Estimates” or “Project Inquiries” pipeline. Usually has automation that triggers a follow-up SMS within 5 minutes.

Fields: Email only (sometimes Name).

GHL location target: “Newsletter” or “Marketing List” pipeline. Should auto-add to an email nurture sequence.

Fields: progressive (Name & Email → Service → Project size → Budget → Timeline → Submit). Sometimes 5-7 screens.

GHL location target: depends on the qualification logic. Often routes to different pipelines based on answers (e.g., “Hot lead” if budget > $X, “Nurture” if below).

These take longer to swap. Build in GHL Forms first, get the embed code, then drop in.


  1. Log into GHL → Sub-account → Sites → Forms
  2. Find the existing form OR create a new one matching the source’s fields
  3. Click Integrate → choose HTML embed (NOT iframe — the iframe option doesn’t style well in Astro)
  4. Copy the snippet — it’s typically:
    <iframe
    src="https://api.leadconnectorhq.com/widget/form/<FORM_ID>"
    style="width:100%;height:600px;border:none;border-radius:0px"
    id="inline-<FORM_ID>"
    data-layout='{"id":"INLINE"}'
    data-trigger-type="alwaysShow"
    data-form-name="<form name>"
    data-height="600"
    ></iframe>
    <script src="https://link.msgsndr.com/js/form_embed.js"></script>

The script tag at the bottom is what makes the iframe auto-size to its content. Include it once per page.


Forms are in src/data/<page>.body.html. Search for <form to find them:

Terminal window
grep -rln "<form" src/data/

You’ll get a list of pages that have forms. Open each.

Looks like:

<form action="https://oldsite.com/submit" method="POST" class="...">
<label>Name</label><input name="name" required>
<label>Email</label><input name="email" type="email" required>
...
<button type="submit">Send</button>
</form>

Note: the surrounding <section> or container styling. You’ll keep that, replace only the <form> tag and its contents.

Replace the entire <form>...</form> block with the GHL iframe + script:

<iframe
src="https://api.leadconnectorhq.com/widget/form/<FORM_ID>"
style="width:100%;border:none;"
id="inline-<FORM_ID>"
data-layout='{"id":"INLINE"}'
data-trigger-type="alwaysShow"
data-form-name="Contact"
data-height="600"
></iframe>

If this is the first GHL embed on the page, also add the script tag at the end of the body:

<script src="https://link.msgsndr.com/js/form_embed.js"></script>

GHL forms render inside the iframe, so external CSS doesn’t reach them. Within GHL Forms editor:

  • Set fonts to match the client’s site
  • Set button colors to match
  • Set field border radius / spacing
  • Set max-width on the form to match the surrounding section

The iframe itself can be styled (width, padding around it). The contents are GHL-controlled.

  1. Build + deploy the change to a preview branch (Cloudflare Pages auto-deploys branches)
  2. Visit the preview URL
  3. Fill the form with test data — use an email like test+ferran-contact@tektongrowth.com so you can identify it later
  4. Submit
  5. Open GHL → Contacts → search for the test email
  6. Confirm the contact was created in the right location/pipeline
  7. Confirm any automation fired (welcome email, SMS, pipeline assignment)

If anything failed: check the iframe URL is correct, check the form is published in GHL, check the GHL location has the right pipelines.

After all forms are wired:

## Forms wired (2026-05-01)
| Page | Form name | GHL Form ID | GHL Location | Pipeline |
|------|-----------|-------------|--------------|----------|
| / | Contact | abc123 | Ferran Landscape | General Inquiries |
| /quote | Free Quote | def456 | Ferran Landscape | Project Inquiries |
| (footer) | Newsletter | ghi789 | Ferran Landscape | Newsletter |

This makes future audits and client questions much easier.


”The iframe is rendering but the form looks unstyled”

Section titled “”The iframe is rendering but the form looks unstyled””

GHL forms inherit ZERO CSS from the parent page. All form styling happens inside GHL Forms editor. Go back to GHL → Forms → Edit and set the styling there.

”The iframe height is wrong (cut off or huge empty space below)”

Section titled “”The iframe height is wrong (cut off or huge empty space below)””

The form_embed.js script handles auto-sizing. Make sure:

  • The script tag is on the page (<script src="https://link.msgsndr.com/js/form_embed.js"></script>)
  • The iframe has data-height="600" or similar (the script uses this as initial; auto-resizes after load)
  • The iframe has id="inline-<FORM_ID>" (the script targets by ID)

“The form submits but no contact appears in GHL”

Section titled ““The form submits but no contact appears in GHL””
  • Check the form is Published in GHL (not Draft)
  • Check the iframe URL has the right FORM_ID
  • Check the form’s location matches what you expect
  • Check spam filters in GHL — sometimes leads get auto-tagged as spam

Shouldn’t happen with the api.leadconnectorhq.com iframe. If it does: check the embed URL is exactly correct (no typos in the form ID), and check there’s no Content Security Policy on the page blocking iframes.


Inventory: which forms exist on which sites

Section titled “Inventory: which forms exist on which sites”

Maintain this table per-client in the client log. As cutover happens, every row should have a GHL Form ID assigned.

| Client | Page | Form purpose | Source CMS form ID | New GHL Form ID | GHL Pipeline |
|--------|------|--------------|--------------------|-----------------|--------------|
| Leon's | / | Get a quote | (squarespace block) | TBD | Project Inquiries |
| Leon's | /contact | Contact us | (squarespace block) | TBD | General Inquiries |

For a single form:

  • GHL form created with matching fields
  • Embed code in the right src/data/<page>.body.html
  • Form renders correctly on local dev server
  • Test submission lands in correct GHL location/pipeline
  • Documented in per-client log

For a full client site:

  • Every <form> on the source site has a GHL embed equivalent
  • Every GHL embed tested and confirmed working
  • CSM signed off on routing for each form
  • No orphan source-CMS form code left in the repo (search for <form returns zero hits)

  • v1.0 (2026-05-01): Initial SOP. Captures the form rewiring step that gates every cutover.