Learn about the many mechanisms Converly has in place to prevent double-counting conversions.
Preventing duplicate submissions
It is possible for a lead to submit a form twice on your site in a manner that should only count as one conversion.
For instance, they might complete the form, hit the submit button, but the submission is rejected because they missed a required field or entered an invalid input (i.e. they enter an email address without the @ symbol). They then correct the error and submit the form again.
To prevent these two form submission attempts from being counted as two conversions, Converly listens for a 'submission success' signal being sent by the form tool and only fires the conversion when it is received. This prevents rejected submissions (like when a required field is left blank) from being counted as a conversion.
This is different for every form tool, and you can read more about how it works in our article on Form Detection.
Deduplication inside Converly
Converly will not record the same conversion twice regardless of how many times it arrives. Five separate mechanisms prevent it, each one catching the duplicates the one before it missed:
The form tool announces success more than once. This is far more common than it sounds. Fluent Forms fires its success signal twice, once on the form itself and once on the page body. Contact Form 7 sends two of them when a WordPress caching plugin has loaded its script twice. Elementor's success event gets re-triggered by other plugins on the page, and HubSpot occasionally sends its own a second time. Converly handles each of these on a tool by tool basis, either by listening to only one of the duplicate signals or by marking the form as already being processed and ignoring anything that follows it.
A conversion fails to send and is retried. If the visitor's connection drops or times out mid-send, the conversion is held in a short queue in their browser and sent again on the next page they load (for up to 30 minutes). It carries the same identifier as the first attempt, so the retry cannot create a second conversion.
The same identifier arrives twice. In rare cases, the Converly code snippet you place on your site can send the conversion to our servers, the conversion is saved successfully, but the response never makes it back to the visitor's browser. The browser assumes the worst and sends it again, but because a conversion is given its identifier by our JavaScript snippet as soon as it happens (as opposed to when it's received by our servers), Converly will recognise the second one is a duplicate, will disregard it, and report back to the browser that the conversion already exists.
One conversion arrives in two pieces. With some form tools, we receive the signal that the form was submitted successfully via the JavaScript snippet you place on your site, but we have to fetch the lead's name, email, phone, etc via the tools API. These are two separate pieces of information about one conversion, and they arrive from different places at different times. Converly joins them rather than recording each of them separately. See How conversions are detected.
Your own code reports the same conversion twice. When your backend reports a conversion through Converly's API, you supply your own identifier for it (often a user or account ID from your database). Converly keeps a record of every identifier that has already fired, held for 18 months. So an API call your code retries after a timeout, or a returning customer signing in months later, does not create a second conversion.
Between them, these mean a visitor double-clicking the submit button, a page being refreshed, a connection dropping halfway, a plugin firing an event twice, or your own code running twice, all end up as a single conversion.
Deduplicating in ad platforms
Most ad platforms recommend you fire a conversion browser-side (i.e. you send an event to the Google Tag/Facebook Pixel on the website) and also send the same conversion server-side as well.
The goal is redundancy. If either of the conversions don't arrive, maybe because an ad blocker stops the Google Tag from loading on the site so therefore the browser-side conversion event is never seen, then the idea is that the other conversion still arrives and it can be recorded successfully.
But what happens if both of them arrive? How does the ad platform know not to count them as two conversions?
The mechanism is slightly different by platform, but the general idea is that Converly sends a matching identifier with both the browser-side conversion and the server-side conversion and the ad platform then uses that shared identifier to deduplicate the conversion.
Here's the identifiers Converly sends to each platform:
| Platform | Identifier | Description |
|---|---|---|
| Meta | event_id | The value passed to the pixel as eventID is the same value sent with the Conversions API event. Meta keeps whichever of the two arrived first and discards the other. |
| Google Ads | transactionId | A stable transaction identifier derived from the event itself, so a repeat upload of the same conversion is recognised rather than added. |
| GA4 | transaction_id | GA4 only deduplicates purchase events by transaction ID, so the same protection does not exist for lead events. Converly accounts for this by never re-firing a GA4 event that has already been sent, rather than relying on GA4 to catch it. |
eventId | Shared between the Insight Tag and the Conversions API. LinkedIn always keeps the Insight Tag event and deducts the duplicate from the Conversions API count, so the two appear separately in reporting. | |
| TikTok | event_id | The same identifier is sent to the pixel and to the Events API. TikTok recognises the pair and counts it once. |
conversion_id | Sent as metadata.conversion_id on the server event and as conversionId on the pixel. | |
| ChatGPT Ads | event_id | The same identifier is sent to the browser tag and with the server event. |
| Microsoft Ads | eventId | Shared between the UET tag and the Conversions API, along with the same tag ID and event name. |
event_id | Pinterest keeps the first event it captured and removes duplicates within 48 hours. | |
| Snapchat | client_dedup_id | Used for all events except purchases, which deduplicate on transaction_id instead. 48 hour window. |
| X Ads | conversion_id | Sent with both the pixel event and the Conversions API event. Only events received within 48 hours of each other are deduplicated. |
What this does not solve
Our deduplication systems prevent accidentally double counting the same conversion event.
They do not prevent two genuinely separate submissions from the same person being sent to your ad platforms and analytics tools, and that is by design. If someone submits your contact form twice in a week, that is two separate conversion events and should be treated as such.
If you prefer those to be counted as one conversion, then there are settings inside the ad platforms and analytics tools for this. For example, In Google Ads you can set a conversion to be counted once per ad click, and in Google Analytics you can set a conversion to only be counted once per session.
