Written by IILL Editorial. Validate event names and success conditions against the site’s measurement contract.
A landing-page conversion should be measured when the server confirms the enquiry, not when someone clicks a CTA. Combining clicks, attempts, successes, and failures inflates lead counts and hides broken forms.
The smallest useful funnel is page_view → contact_click → submit_intent → submit_success. Keep submit_failure beside it as a reliability signal.
Define the meaning of each step
| Step | Example event | Trigger | Primary conversion? |
|---|---|---|---|
| Visit | page_view |
The landing page renders | No |
| Interest | contact_click |
A form, phone, or email CTA is used | No |
| Submit intent | contact_form_submit_intent |
A valid request is about to be sent | No |
| Lead success | contact_form_submit_success |
The server confirms storage or delivery | Yes |
| Lead failure | contact_form_submit_failure |
Validation, network, or server delivery fails | No |
GA4 recommends generate_lead when someone submits a form or request. Use it
when that meaning matches the organisation’s reporting contract. On this site,
a completed lead means server-confirmed success: a request that was sent but
never stored or delivered is a failure, not a lead. Fire generate_lead after
confirmation, or keep the existing custom success event and document the
mapping. Do not rename a stable event merely for fashion.
Event → key event → Google Ads conversion
These are three separate decisions:
- Event: the site sends
contact_form_submit_successafter the server confirms the result. - Key event: GA4 marks that event as important to the business and includes it in key-event reporting.
- Google Ads conversion: if GA4 and Google Ads are linked, the key event can be created or imported as a conversion used for advertising measurement and, when configured, bidding.
Promote the same server-confirmed outcome through the chain. Do not promote a CTA click merely because it happens earlier and produces more data. Analytics and Ads can still differ because their attribution, windows, time zones, and settings differ, so document the exact event and configuration rather than promising identical totals.
Why a click is not a lead
After clicking, a visitor may still encounter:
- a required-field error;
- a lost network connection;
- a server error;
- failed storage or email delivery;
- duplicate requests from repeated clicks.
Counting the click makes the campaign look successful even when nothing reaches the team. Keep clicks as a diagnostic for copy and CTA placement. Mark only the confirmed outcome as a key event.
Worked example: what counting clicks would report
Take one landing page over one month, with 1,000 landing sessions. The numbers are illustrative.
From 120 clicks to 38 leads
contact_click120contact_form_submit_intent45contact_form_submit_success38contact_form_submit_failure7If contact_click were the key event, the report would show 120 leads. The team
received 38. With the ratios below, the CTA interest rate is 12%, the attempt
rate 4.5%, and the completion rate 84%. The seven failures are 16% of attempts,
roughly one in six: a form problem to fix today, not a campaign result.
Implementation sequence
1. Keep context small and bounded
Send only values a report will use, such as locale, page_type,
content_group, ui_location, and contact_method. Do not turn changing button
copy or free text into a custom dimension.
gtag("event", "contact_click", {
locale: "en",
page_type: "landing_page",
ui_location: "hero",
contact_method: "form"
});
2. Record intent when a valid request starts
Fire submit intent after browser validation passes and immediately before the request begins. A click listener on the submit button alone misses keyboard submission and cannot distinguish a validation failure.
3. Separate success and failure after the response
Send contact_form_submit_success only after a successful server response. Send
contact_form_submit_failure with a bounded result class for an error. Never
send the raw error, form fields, or email address.
4. Prevent duplicates
Disable repeated submission while the request is in progress and use server idempotency where appropriate. Make sure the GA event does not fire twice for one result. If a thank-you page is also used, check that the callback and the new page do not both count the same lead.
UTM parameters label acquisition; they are not user-data fields
Use an agreed utm_source, utm_medium, and utm_campaign on external campaign
links. Do not put UTMs on internal navigation, where they can overwrite the
original session acquisition. Allowlist and normalise campaign values instead
of forwarding an arbitrary query string.
For example:
utm_source:google,newsletter, or an agreed publisher name;utm_medium:cpc,organic, oremail;utm_campaign: a short campaign ID owned by the team.
Never put names, email addresses, phone numbers, enquiry text, or internal customer IDs in campaign or event parameters. GA4 is not the CRM record.
Case: how HTML2WEB separates checkout intent from payment
HTML2WEB, IILL’s HTML sharing tool, applies the same split to payments. It records checkout in its own database in four steps:
checkout_intent_clickedwhen a visitor presses a pricing button, with the offer, payment provider, button location, and whether checkout was open;- a checkout start when the payment page is created;
- a return from the payment page; and
- activation, written only when the payment provider’s webhook confirms the order.
Only activation counts as a sale. A return from the payment page does not,
because a buyer can come back without paying. Before checkout opened, the
pricing buttons still worked: a press recorded checkout_intent_clicked with
the result unavailable and showed a notice in the visitor’s language. That
measured demand without calling a click a sale. Traffic marked as QA stays out
of the decision report.
Template: one contract per key event
Keep one short contract for each event you promote. Review it whenever the form or the server response changes.
event: contact_form_submit_success
fires_when: the server confirms the enquiry was stored or delivered
key_event: true
ads_conversion: imported from GA4 # or: none
parameters:
locale: [en, ko, ja]
page_type: [landing_page, service, contact]
contact_method: [form]
never_send: [name, email, phone, message, raw_error, free_text_query]
duplicates: one event per server result; submit disabled while sending
qa: internal traffic marked before launch
owner: web team
verified_on: 2026-09-25
Pre-launch QA
- Mark one dedicated browser as QA traffic.
- Run a CTA click, valid attempt, success, and failure once each.
- Inspect the browser payload for the event name and bounded parameters.
- Confirm ordering and receipt in GA4 Realtime or DebugView.
- Confirm that the server really stored or delivered the enquiry.
- Keep QA distinguishable in analysis without immediately deleting raw evidence.
Google’s lead-form reporting guide shows how to examine drop-off from visit to submission in a funnel exploration. Create a custom definition only after the parameter is collected and a report needs it. New definitions do not backfill historical data.
Four ratios to keep in the first report
- CTA interest rate =
contact_click / landing sessions - Form attempt rate =
submit_intent / landing sessions - Completion rate =
submit_success / submit_intent - Failure rate =
submit_failure / submit_intent
Begin with locale, landing page, and source/medium. Splitting a small sample by every button, device, and campaign produces noise. Review demand in comparable 28-day windows, but investigate form failures immediately as an operational problem.
Next action: submit one real test enquiry and trace it from the browser payload through GA4 DebugView to the inbox or database record that proves the server kept it. If Ads is linked, confirm the same event appears in the intended conversion action. If the page type is still undecided, read website versus landing page. To plan the form and measurement contract together, discuss the scope with IILL.