Proposal ยท 2 October 2026
We checked every attribute we send against what MoEngage actually received, rather than against what the tags are configured to send. 13 arrive empty or do not arrive at all, 17 tags send a value MoEngage already collects for free, and 42 have never been observed because their event has not fired. We propose removing 20 and adding 4, with the evidence for each.
Before and after
Attributes today
105
Across 24 live events. The table also lists the 4 additions and one held-back attribute being retired
After this change
89
20 dropped, 4 added
Measurably wrong today
13
3 never arrive at all
Never yet observed
42
Those events have not fired since we began measuring
Every figure on this page is counted from 4 MoEngage Activity Info exports, not from what the tags are configured to send. The two disagree, which is the point.
The cause
The schema named the value it wanted. The tag was then pointed at the closest-looking Tag Manager variable, without checking the website supplies that value. Nothing fails loudly when it does not: the tag still reports success, and MoEngage quietly stores a blank or drops the key.
An attribute arriving empty is not harmless. MoEngage fixes an attribute's data type permanently from the first event it sees. A blank sent once types that attribute forever. It is exactly why nine attributes were deliberately held back rather than sent empty, and sending blanks elsewhere undoes that care.
Three examples, each measured rather than assumed:
form_id on lead_form_opened is wired to a Tag Manager
built-in that only fills on form submissions. The event fires on the form becoming
visible, so it reads nothing. Empty in 46 of 47.
source is wired to the traffic source, where the schema means where on
the page. It is undefined on a direct visit, so MoEngage drops the key. It has never
arrived once, on either event that sends it.
page_url is the page address, which MoEngage already records on every
event as URL. Identical in 49 of 52 blocks we compared.
What we are applying
MoEngage collects these on every event without being sent them:
session_id, device_type, utm_source, utm_medium, utm_campaign, timestamp, URL.
Not just attributes
Element Visibility on form.ui-form, 50% on screen, once per element
Click on the four CTA selectors, plus Element Visibility retained ONLY for the inline form on /contact-us/
Three fixes in one change. The CTA identity exists only at click time: all four CTAs open ONE shared modal whose markup carries no id, no data-*, and an EMPTY <h2> title, so no variable reading the form can recover which button opened it. A click trigger also makes the event mean someone CHOSE to open a form rather than a form scrolled past, which is what produced 16 fires in one sitting.
Because this changes what the event counts, its history is not comparable across the change. Worth knowing before anyone reads a step in a chart as a real movement.
The detail
| Event | Attribute | Verdict | Wired to today | What arrived | Proposed |
|---|---|---|---|---|---|
| project_switch_clicked | from_project_name | Keep | {{RegEx Table - project_name}} | ok | unchanged |
| project_switch_clicked | to_project_name | Keep | {{Custom JS - clicked_project_name}} | ok | unchanged |
| site_visit_cta_clicked | project_name | Keep | {{RegEx Table - project_name}} | ok | unchanged |
| site_visit_cta_clicked | cta_name | Keep | {{Click Text}} | ok | unchanged |
| site_visit_cta_clicked | source | Drop | {{URL - utm_source}} | NEVER ARRIVES | removed |
| WhyWired to {{URL - utm_source}}, which is a TRAFFIC source where the schema means where on the page. Undefined on a direct visit, so MoEngage drops the key entirely and it has never once arrived. utm_source is also already collected free. | |||||
| site_visit_cta_clicked | cta_location | Add | not sent | new | {{CJS - cta_location}} |
| WhySame reason as lead_form_opened: cta_name alone cannot say which Request private Tour was clicked. | |||||
| brochure_download_clicked | project_name | Keep | {{RegEx Table - project_name}} | ok | unchanged |
| brochure_download_clicked | project_location | Keep | {{RegEx Table - project_location}} | ok | unchanged |
| brochure_download_clicked | page_url | Drop | {{Page URL}} | ok | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| brochure_download_clicked | page_type | Keep | {{RegEx Table - page_type}} | ok | unchanged |
| compare_projects_clicked | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| compare_projects_clicked | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| compare_projects_clicked | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| compare_projects_clicked | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| lead_form_opened | form_id | Rewire | {{Form ID}} | sometimes empty (46/47) | {{CJS - form_id}} |
| Why{{Form ID}} is a built-in that populates on FORM events; this trigger is Element Visibility, so it reads nothing. Measured empty in 46 of 47. The site's own code computes formId internally and never puts it on the DOM, but it is derivable: project_enquiry_modal inside the open enquiry dialog, contact_us_body inside section#enquire. | |||||
| lead_form_opened | project_name | Keep | {{RegEx Table - project_name}} | sometimes empty (14/47) | unchanged |
| WhyWorks. Empty in 14 of 47 and every one of those is off a project page, which is correct. | |||||
| lead_form_opened | source | Drop | {{URL - utm_source}} | NEVER ARRIVES | removed |
| WhyWired to {{URL - utm_source}}, which is a TRAFFIC source where the schema means where on the page. Undefined on a direct visit, so MoEngage drops the key entirely and it has never once arrived. utm_source is also already collected free. | |||||
| lead_form_opened | form_type | Drop | not sent | held back, never sent | removed |
| WhyHeld back since day one and not buildable as defined. page_type is not the form's own type, and the site has one form type per page kind, which form_id now carries. | |||||
| lead_form_opened | cta_name | Add | not sent | new | {{Click Text}} |
| WhyEnquire, Brochure, Private Tour or Request private Tour. The question the event could not answer. | |||||
| lead_form_opened | cta_location | Add | not sent | new | {{CJS - cta_location}} |
| Whysecondary_nav, project_details, lets_connect or contact_page_body, from the nearest ui- section class. This is what separates the sub-nav Enquire from the header Enquire, which cta_name cannot. | |||||
| location_connectivity_viewed | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| location_connectivity_viewed | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| location_connectivity_viewed | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| location_connectivity_viewed | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| location_connectivity_viewed | location_topic | Keep, unverified | {{Click Text}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| primary_cta_clicked | project_name | Keep | {{RegEx Table - project_name}} | sometimes empty (7/36) | unchanged |
| primary_cta_clicked | project_location | Keep | {{RegEx Table - project_location}} | sometimes empty (7/36) | unchanged |
| primary_cta_clicked | page_url | Drop | {{Page URL}} | ok | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| primary_cta_clicked | page_type | Keep | {{RegEx Table - page_type}} | ok | unchanged |
| primary_cta_clicked | cta_name | Keep | {{Click Text}} | ok | unchanged |
| primary_cta_clicked | destination_url | Rewire | {{Click URL}} | sometimes empty (30/36) | {{Click URL}}, held back when empty |
| WhyEmpty in 30 of 36, every one a CTA that opens a modal rather than navigating. Correct to be absent, wrong to be sent blank. | |||||
| primary_cta_clicked | cta_location | Add | not sent | new | {{CJS - cta_location}} |
| Whycta_name read ENQUIRE for 11 of 36 clicks across two different buttons. Today they are only tellable apart by destination_url being empty, which is an accident rather than an identifier. | |||||
| project_card_clicked | project_name | Keep | {{RegEx Table - project_name}} | ok | unchanged |
| project_card_clicked | project_location | Keep | {{RegEx Table - project_location}} | ok | unchanged |
| project_card_clicked | page_url | Drop | {{Page URL}} | ok | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| project_card_clicked | page_type | Keep | {{RegEx Table - page_type}} | ok | unchanged |
| project_card_clicked | destination_url | Keep | {{Click URL}} | ok | unchanged |
| project_page_viewed | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_page_viewed | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_page_viewed | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| project_page_viewed | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| qr_code_scan_landing | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| qr_code_scan_landing | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| qr_code_scan_landing | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| qr_code_scan_landing | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| qr_code_scan_landing | campaign_name | Keep, unverified | {{URL - utm_campaign}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| website_visit | project_name | Keep | {{RegEx Table - project_name}} | ALWAYS EMPTY | unchanged |
| WhyEmpty in all 25, but every one fired off a project page where empty is correct. Keep and re-measure once it fires on a project page. | |||||
| website_visit | project_location | Keep | {{RegEx Table - project_location}} | ALWAYS EMPTY | unchanged |
| WhySame as project_name. | |||||
| website_visit | page_url | Drop | {{Page URL}} | ok | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| website_visit | page_type | Keep | {{RegEx Table - page_type}} | ok | unchanged |
| faq_viewed | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| faq_viewed | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| faq_viewed | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| faq_viewed | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| faq_viewed | faq_question | Keep, unverified | {{Click Text}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_video_completed | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_video_completed | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_video_completed | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| project_video_completed | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_video_completed | video_id | Investigate | {{Custom JS - youtube_video_id}} | no data yet | {{Custom JS - youtube_video_id}} |
| WhySame variable as project_video_played. No data yet; settle it there. | |||||
| project_video_completed | watch_seconds | Keep, unverified | {{Video Current Time}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_video_completed | completion_pct | Keep, unverified | {{Video Percent}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| amenity_viewed | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| amenity_viewed | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| amenity_viewed | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| amenity_viewed | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| amenity_viewed | amenity_name | Keep, unverified | {{Click Text}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| configuration_viewed | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| configuration_viewed | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| configuration_viewed | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| configuration_viewed | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| configuration_viewed | configuration | Keep, unverified | {{Click Text}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| floor_plan_viewed | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| floor_plan_viewed | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| floor_plan_viewed | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| floor_plan_viewed | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| pricing_section_clicked | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| pricing_section_clicked | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| pricing_section_clicked | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| pricing_section_clicked | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| pricing_section_clicked | price_band | Keep, unverified | {{Click Text}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_section_viewed | project_name | Keep, unverified | {{RegEx Table - project_name}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_section_viewed | project_location | Keep, unverified | {{RegEx Table - project_location}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_section_viewed | page_url | Drop | {{Page URL}} | no data yet | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| project_section_viewed | page_type | Keep, unverified | {{RegEx Table - page_type}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_section_viewed | section_name | Keep, unverified | {{Click Text}} | no data yet | unchanged |
| WhyThis event has not fired since the exports began, so the attribute has never been observed arriving. | |||||
| project_video_played | project_name | Keep | {{RegEx Table - project_name}} | ok | unchanged |
| project_video_played | project_location | Keep | {{RegEx Table - project_location}} | ok | unchanged |
| project_video_played | page_url | Drop | {{Page URL}} | ok | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| project_video_played | page_type | Keep | {{RegEx Table - page_type}} | ok | unchanged |
| project_video_played | video_id | Investigate | {{Custom JS - youtube_video_id}} | NEVER ARRIVES | {{Custom JS - youtube_video_id}} |
| WhyNever arrives across 6 events. The embed URL DOES carry the id (/embed/YO7ZHbLSpl0?...) and the regex should match it, so the cause is not yet known. Reproduce in Preview and read {{Video URL}} at the moment the trigger fires before changing anything. | |||||
| lead_form_abandoned | form_id | Keep | {{DLV - lead_form_id}} | ok | unchanged |
| lead_form_abandoned | fields_completed | Keep | {{DLV - lead_fields_completed}} | ok | unchanged |
| lead_form_abandoned | abandonment_step | Keep | {{DLV - lead_abandonment_step}} | ok | unchanged |
| lead_form_abandoned | time_to_abandon | Keep | {{DLV - lead_time_to_abandon_seconds}} | ok | unchanged |
| lead_submitted | project_name | Keep | {{DLV - lead_project}} | ok | unchanged |
| lead_submitted | enquiry_type | Keep | {{DLV - lead_enquiry_type}} | sometimes empty (16/22) | unchanged |
| WhyEmpty in 16 of 22 and every one is a form other than Contact Us, where the select does not render. Correct. | |||||
| lead_submitted | location | Keep | {{DLV - lead_location}} | sometimes empty (16/22) | unchanged |
| WhySame as enquiry_type. | |||||
| otp_verified | verification_method | Keep | {{DLV - otp_verification_method}} | ok | unchanged |
| otp_verified | verification_status | Keep | {{DLV - otp_verification_status}} | ok | unchanged |
| brochure_downloaded | project_name | Keep | {{DLV - project_slug}} | ok | unchanged |
| brochure_downloaded | project_location | Keep | {{RegEx Table - project_location}} | ok | unchanged |
| brochure_downloaded | page_url | Drop | {{Page URL}} | ok | removed |
| WhyDuplicates MoEngage's own URL attribute, which arrives free on every event. Measured identical in 49 of 52 blocks; the 3 differences are a #fragment and a gtm_debug parameter, i.e. the same page. | |||||
| brochure_downloaded | page_type | Keep | {{RegEx Table - page_type}} | ok | unchanged |
| brochure_downloaded | brochure_id | Keep | {{DLV - brochure_id}} | ok | unchanged |
| brochure_downloaded | brochure_type | Keep | {{DLV - brochure_type}} | ok | unchanged |
| brochure_downloaded | configuration | Keep | {{DLV - configuration}} | ALWAYS EMPTY | unchanged |
| WhyEmpty in both events, and correctly so: a project-level brochure has no single configuration. Fills when a configuration-specific brochure exists. | |||||
| lead_form_partially_completed | form_id | Keep | {{DLV - lead_form_id}} | ok | unchanged |
| lead_form_partially_completed | fields_completed | Keep | {{DLV - lead_fields_completed}} | ok | unchanged |
| lead_form_partially_completed | last_field_completed | Keep | {{DLV - lead_last_field_completed}} | ok | unchanged |
Nothing matches that filter.