GoHighLevel
Form Embed Swap (Source CMS → GHL)
SOP: Form Embed Swap (Source CMS → GHL)
Section titled “SOP: Form Embed Swap (Source CMS → GHL)”Last Updated: 2026-05-01 Version: 1.0 Tier: Cutover prerequisite
Purpose
Section titled “Purpose”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.
How form rewiring fits into cutover
Section titled “How form rewiring fits into cutover”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/<page>.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:#fffThe 4 form types we encounter
Section titled “The 4 form types we encounter”Most client sites have one or more of these. Each has a slightly different swap pattern.
Type 1: Contact form (most common)
Section titled “Type 1: Contact form (most common)”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.
Type 2: Quote / estimate form
Section titled “Type 2: Quote / estimate form”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.
Type 3: Newsletter / mailing list
Section titled “Type 3: Newsletter / mailing list”Fields: Email only (sometimes Name).
GHL location target: “Newsletter” or “Marketing List” pipeline. Should auto-add to an email nurture sequence.
Type 4: Multi-step / qualifying form
Section titled “Type 4: Multi-step / qualifying form”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.
How to get the GHL embed code
Section titled “How to get the GHL embed code”- Log into GHL → Sub-account → Sites → Forms
- Find the existing form OR create a new one matching the source’s fields
- Click Integrate → choose HTML embed (NOT iframe — the iframe option doesn’t style well in Astro)
- Copy the snippet — it’s typically:
<iframesrc="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.
Swap procedure
Section titled “Swap procedure”Step 1: Find the form in the cloned repo
Section titled “Step 1: Find the form in the cloned repo”Forms are in src/data/<page>.body.html. Search for <form to find them:
grep -rln "<form" src/data/You’ll get a list of pages that have forms. Open each.
Step 2: Identify the form block
Section titled “Step 2: Identify the form block”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.
Step 3: Replace with the GHL embed
Section titled “Step 3: Replace with the GHL embed”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>Step 4: Style the iframe to match
Section titled “Step 4: Style the iframe to match”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.
Step 5: Test the submit
Section titled “Step 5: Test the submit”- Build + deploy the change to a preview branch (Cloudflare Pages auto-deploys branches)
- Visit the preview URL
- Fill the form with test data — use an email like
test+ferran-contact@tektongrowth.comso you can identify it later - Submit
- Open GHL → Contacts → search for the test email
- Confirm the contact was created in the right location/pipeline
- 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.
Step 6: Document in the per-client log
Section titled “Step 6: Document in the per-client log”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.
Common issues
Section titled “Common issues””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
”CORS error in the console”
Section titled “”CORS error in the console””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 |Definition of done
Section titled “Definition of done”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
<formreturns zero hits)
Version Control
Section titled “Version Control”- v1.0 (2026-05-01): Initial SOP. Captures the form rewiring step that gates every cutover.