Time-Gated Submission Detection + Geo/Traffic Enrichment for Pipedrive Web Forms
A dataLayer enrichment script for Pipedrive's embedded web forms — detects real form submissions (filtering out the iframe's initial resize postMessage, which looks identical to a submit event), and enriches the event with traffic attribution, click IDs, IP geolocation, and device/tech data.
Built and maintained by MD Niamul — Founder, Digital Soldier Agency. Data Analytics Architect & Conversion Tracking Partner. Official Stape partner.
Pipedrive's embedded web form iframe sends a postMessage with payload.source === 'pipedriveWebForms' on load (to tell the parent page how tall to resize the iframe) — and that message has the same shape as an actual form-submission message. Without filtering, this fires a false "conversion" the instant the form loads, before the visitor has done anything.
This script fixes that with two guards:
- Time gate — any Pipedrive message received within 3 seconds of page load is treated as the iframe's resize event and ignored. Real submissions require the visitor to fill in fields first, so they essentially never happen inside that window.
- Debounce — a second identical message within 2 seconds of the last accepted one is ignored, guarding against Pipedrive occasionally sending the confirmation event twice.
Both windows are hardcoded (3000ms / 2000ms) — see Customization to adjust them.
This script does NOT capture contact PII (email, phone, name, company) from Pipedrive submissions.
Pipedrive's web form iframe does not expose submitted field values to the parent page via postMessage — only a generic "form submitted" signal with a form UUID. Because of this, contact_email, contact_phone, contact_first_name, contact_last_name, and contact_company are hardcoded to empty strings in the payload, and the corresponding hashed_email / hashed_phone / hashed_firstname / hashed_lastname fields are always empty too.
What this script can still do reliably:
- Fire a clean, de-duplicated
pipedrive_form_submitconversion event (for GA4/Ads conversion counting) - Attach full traffic attribution (source/medium/campaign, all click IDs)
- Attach IP geolocation, with
hashed_city/hashed_state/hashed_zip/hashed_countrypopulated (geo data comes from the IP lookup, not the form, so it works fine) - Attach GA4 client ID, device/tech info, and marketing cookies
What it cannot do without a workaround:
- Enhanced Conversions / CAPI matching on the actual submitted email or phone — there's no submitted-value data to hash
If you need contact-level match data: the reliable fix is server-side — use Pipedrive's own webhook (fires on new Person/Deal creation, with full field data) into your CRM/sGTM pipeline instead of relying on the client-side iframe message. This script is best used as the client-side attribution layer that a server-side Pipedrive webhook integration then joins against (matched by timestamp + IP, or by a hidden UTM/click-ID field you pass into the Pipedrive form URL).
The file includes two SHA-256 implementations: an incomplete sha256() (left mid-implementation, returns a placeholder string, and is never actually called anywhere in the script) and a complete, working sha256_secure() (used for all real hashing). The dead sha256() function is harmless as-is — since nothing calls it — but it's safe to delete if you want to slim the file down.
Pushes pipedrive_form_submit to window.dataLayer on a confirmed real submission:
{
event: 'pipedrive_form_submit',
traffic_source: '...', traffic_medium: '...', traffic_campaign: '...', traffic_campaign_id: '...',
event_id: 'pd_...', client_id: '...',
conversion_time: '...ISO...', conversion_timestamp: 173..., conversion_date: 'YYYY-MM-DD', conversion_timezone: '...',
user_agent: '...', screen_resolution: '...', viewport_size: '...', browser_language: '...', device_type: 'Desktop', os_name: 'Windows',
form_id: '...', form_type: 'pipedrive_webform',
contact_email: '', contact_phone: '', contact_first_name: '', contact_last_name: '', contact_company: '', // always empty — see limitation above
hashed_email: '', hashed_phone: '', hashed_firstname: '', hashed_lastname: '', // always empty — see limitation above
hashed_city: '...', hashed_state: '...', hashed_zip: '...', hashed_country: '...', // populated from IP geo
external_id: '', user_id: '', session_id: '...',
user_ip: '...', user_country: '...', user_country_id: '...', user_city: '...', user_region: '...',
user_province: '...', user_postal_code: '...', user_continent: '...', user_latitude: '...', user_longitude: '...',
gclid: '', gbraid: '', wbraid: '', dclid: '', fbclid: '', ttclid: '', msclkid: '', li_fat_id: '',
twclid: '', epik: '', sclid: '', rdt_cid: '', tblci: '', dicbo: '', amzn_id: '', qclid: '', clickid: '',
cookie_ga: '...', cookie_gid: '...', cookie_gcl_au: '...', cookie_fbp: '...', cookie_fbc: '...', tt_webid: '...', cookie_ttp: '...',
page_url: '...', page_title: '...', page_hostname: '...', page_path: '...',
landing_page: '...', referrer: '...', original_referrer: '...'
}- GTM → Tags → New → Custom HTML.
- Paste the contents of
pipedrive-tracking-suite.jswrapped in<script>tags. - Trigger: All Pages (or scoped to pages with an embedded Pipedrive web form).
- Publish.
Paste the same <script>...</script> block before </body> on any page with an embedded Pipedrive form iframe.
- Time-gate window —
if (now - loadTime < 3000)— increase if your form is long/complex and a very fast real submission is getting filtered; decrease if you're confident visitors never submit within 3s and want faster event firing. - Debounce window —
if (now - lastFire < 2000)— adjust if Pipedrive's double-fire behavior needs a wider gap. - Geo provider — currently
geojs.ioonly, no fallback chain. For production reliability at scale, consider adding the multi-provider fallback pattern used in the companionghl-ultimate-tracking-suiterepo.
Like the rest of this tracking suite family, this script captures click IDs, geolocation, and marketing cookies unconditionally — no built-in consent gate. Add a consent check before deploying on EU/UK/consent-regulated traffic (see custom-cookie-consent-banner for a reference CMP implementation).
.
├── pipedrive-tracking-suite.js # the script — GTM Custom HTML ready
└── README.md # this file
ES5-safe throughout, uses XMLHttpRequest for the geo lookup (not fetch) for broad compatibility. Works inside GTM's sandboxed Custom HTML environment.
Built by MD Niamul — Founder & CEO, Digital Soldier Agency. Data Analytics Architect and Conversion Tracking Partner, official Stape partner. Helping agencies and D2C brands turn ad spend into verifiable, accurately-tracked profit through data integrity and server-side architecture.
- Website: mdniamul.com
- Book a call: calendly.com/mdniamul
- LinkedIn: linkedin.com/in/mdniamul
- WhatsApp: +8801776485758
MIT — see LICENSE.