Skills › Marketing Skills › conversion-tracking › detect-fluent-forms.json
detect-fluent-forms.json
104 lines · skills/conversion-tracking/assets/gtm-recipes/detect/detect-fluent-forms.json at 88c79f6
1{
2 "exportFormatVersion": 2,
3 "exportTime": "2026-07-02 00:00:00",
4 "containerVersion": {
5 "path": "accounts/0/containers/0/versions/0",
6 "accountId": "0",
7 "containerId": "0",
8 "containerVersionId": "0",
9 "container": {
10 "path": "accounts/0/containers/0",
11 "accountId": "0",
12 "containerId": "0",
13 "name": "Conversion Detection - Fluent Forms",
14 "publicId": "GTM-XXXXXXX",
15 "usageContext": [
16 "WEB"
17 ],
18 "fingerprint": "0",
19 "tagManagerUrl": "https://tagmanager.google.com/#/container/accounts/0/containers/0/workspaces/0"
20 },
21 "tag": [
22 {
23 "accountId": "0",
24 "containerId": "0",
25 "tagId": "1",
26 "name": "Conversion Detection - Fluent Forms Submission Listener",
27 "type": "html",
28 "parameter": [
29 {
30 "type": "TEMPLATE",
31 "key": "html",
32 "value": "<script>\n(function () {\n if (window.__ctFluentForms) return;\n window.__ctFluentForms = true;\n window.dataLayer = window.dataLayer || [];\n var listeners = [], lastEvent = null;\n // Fluent Forms 6.2.5 reports one success response through three different\n // event objects. Deduplicate by response-object identity and original form\n // node; never inspect or retain a response's fields.\n var seenResponses = typeof WeakMap === 'function' ? new WeakMap() : null;\n window.__ctFluentSubscribe = function (listener) {\n if (listener && typeof listener === 'object') listeners.push(listener);\n };\n function isForm(form) {\n try {\n if (!form || String(form.tagName || '').toLowerCase() !== 'form') return false;\n if (String(form.className || '').indexOf('frm-fluent-form') !== -1) return true;\n if (form.closest && form.closest('.fluentform')) return true;\n return /^fluentform_\\d+$/.test(form.id || '');\n } catch (e) { return false; }\n }\n function asForm(candidate) {\n try {\n var el = candidate;\n if (el && el.jquery && el.length) el = el[0];\n return isForm(el) ? el : null;\n } catch (e) { return null; }\n }\n function notify(phase, form, candidate, event, arg2, arg3) {\n var handled = false;\n for (var i=0;i<listeners.length;i++) {\n try { var fn=listeners[i] && listeners[i][phase]; if(typeof fn==='function' && fn(form,candidate,event,arg2,arg3)===true)handled=true; } catch(e) {}\n }\n return handled;\n }\n function submit(event) {\n try { var form=event.target; if(isForm(form)) notify('beforeAttempt',form,false,event); } catch(e) {}\n }\n function resolve(event,arg2,arg3) {\n try {\n var form=asForm(arg2 && arg2.form) || asForm(arg3) || asForm(arg2);\n if(form)return form;\n var oe=event && event.originalEvent;\n if(oe && oe.detail) return asForm(oe.detail.form);\n return asForm(event && event.target);\n } catch(e) { return null; }\n }\n function responseFor(event, arg2) {\n try {\n var descriptor = arg2 && Object.getOwnPropertyDescriptor(arg2, 'response');\n var response = descriptor && Object.prototype.hasOwnProperty.call(descriptor, 'value') ? descriptor.value : null;\n if (response && typeof response === 'object') return response;\n var originalEvent = event && event.originalEvent;\n var detail = originalEvent && originalEvent.detail;\n descriptor = detail && Object.getOwnPropertyDescriptor(detail, 'response');\n response = descriptor && Object.prototype.hasOwnProperty.call(descriptor, 'value') ? descriptor.value : null;\n return response && typeof response === 'object' ? response : null;\n } catch(e) { return null; }\n }\n function alreadySeen(response, form) {\n try {\n if (!seenResponses || !response || !form || typeof response !== 'object' || typeof form !== 'object') return true;\n var forms = seenResponses.get(response);\n if (!forms) {\n forms = typeof WeakSet === 'function' ? new WeakSet() : null;\n if (!forms) return true;\n seenResponses.set(response, forms);\n }\n if (forms.has(form)) return true;\n forms.add(form);\n return false;\n } catch(e) { return true; }\n }\n function success(event,arg2,arg3) {\n try {\n if (event && typeof event === 'object' && event === lastEvent) return;\n lastEvent=event;\n if (event && typeof event === 'object') setTimeout(function(){if(lastEvent===event)lastEvent=null;},0);\n var form=resolve(event,arg2,arg3);\n if(!form)return;\n var response=responseFor(event,arg2);\n if(!response || alreadySeen(response,form))return;\n if(!notify('onCandidate',form,true,event,arg2,arg3)) window.dataLayer.push({event:'fluent_forms_submitted',form_id:form.id || ''});\n } catch(e) {}\n }\n document.addEventListener('submit',submit,true);\n function hook() {\n try {\n if (window.__ctFluentSuccessHooked || !window.jQuery) return false;\n window.__ctFluentSuccessHooked=true;\n window.jQuery(document).on('fluentform_submission_success',success);\n return true;\n } catch(e) { return false; }\n }\n if(!hook()) {\n document.addEventListener('DOMContentLoaded',hook);\n window.addEventListener('load',hook);\n }\n})();\n</script>"
33 },
34 {
35 "type": "BOOLEAN",
36 "key": "supportDocumentWrite",
37 "value": "false"
38 }
39 ],
40 "firingTriggerId": [
41 "2147479553"
42 ],
43 "tagFiringOption": "ONCE_PER_EVENT",
44 "monitoringMetadata": {
45 "type": "MAP"
46 },
47 "consentSettings": {
48 "consentStatus": "NOT_SET"
49 }
50 }
51 ],
52 "trigger": [
53 {
54 "accountId": "0",
55 "containerId": "0",
56 "triggerId": "2",
57 "name": "CE - Fluent Forms Submitted",
58 "type": "CUSTOM_EVENT",
59 "customEventFilter": [
60 {
61 "type": "EQUALS",
62 "parameter": [
63 {
64 "type": "TEMPLATE",
65 "key": "arg0",
66 "value": "{{_event}}"
67 },
68 {
69 "type": "TEMPLATE",
70 "key": "arg1",
71 "value": "fluent_forms_submitted"
72 }
73 ]
74 }
75 ],
76 "filter": []
77 }
78 ],
79 "variable": [
80 {
81 "accountId": "0",
82 "containerId": "0",
83 "variableId": "1",
84 "name": "DLV - Fluent Form ID",
85 "type": "v",
86 "parameter": [
87 {
88 "type": "TEMPLATE",
89 "key": "name",
90 "value": "form_id"
91 },
92 {
93 "type": "INTEGER",
94 "key": "dataLayerVersion",
95 "value": "2"
96 }
97 ]
98 }
99 ],
100 "fingerprint": "0",
101 "tagManagerUrl": "https://tagmanager.google.com/#/container/accounts/0/containers/0/workspaces/0",
102 "exportTime": "2026-07-05 00:00:00"
103 }
104}