Proposal ยท 2 October 2026

Three attributes have never once arrived.

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

What changes

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

Attributes were specified, then wired to whatever was nearest

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:

What we are applying

Three rules

  1. Every attribute names a value the website actually supplies. If nothing supplies it, it is held back, not sent empty: a blank still types the attribute in MoEngage forever.
  2. Never send what MoEngage already collects. page_url duplicates MoEngage's own URL, measured identical in 49 of 52 event blocks.
  3. An attribute must distinguish the thing it names. cta_name reading ENQUIRE for two different buttons is a label, not an identifier.

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

One event changes what it measures

lead_form_opened

Fires today on

Element Visibility on form.ui-form, 50% on screen, once per element

Proposed

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

Every attribute, and what it actually delivers

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