Feature Description
Building on the existing conversion event tracking infrastructure introduced in the Initial Conversion Event Infrastructure epic, this issue extends Site Kit's event providers (assets/js/event-providers) to send two new custom dimensions alongside the conversion events they already track:
googlesitekit_event_provider — identifies the plugin source of a tracked event (e.g. WooCommerce, Contact Form 7). This enables the Source Tabs in the Online Store Performance widget and the Info Icons on Form tabs in the Lead Generation Performance widget.
googlesitekit_form_id — the ID of the form that triggered a lead generation event. Following the existing pattern of googlesitekit_post_author and googlesitekit_post_category, only the form ID is tracked (not the title), as the title can be queried from wp_posts at reporting time. See Conversion Providers Form ID extraction for the spike findings on form ID extraction per provider.
Both new custom dimensions must also be added to the existing custom dimension definitions and valid-slug allowlists in JS and PHP so existing routes accept and track them correctly.
Acceptance criteria
- When a supported event provider plugin fires a conversion event tracked by Site Kit (within
assets/js/event-providers), the googlesitekit_event_provider custom dimension should be included in the event payload, with a value identifying the specific plugin source (e.g. "woocommerce", "contact-form-7").
- When a supported lead generation event provider fires a form completion event (i.e.
submit_lead_form, contact, or generate_lead), the googlesitekit_form_id custom dimension should also be included in the event payload, containing the integer or string ID of the form that was submitted.
googlesitekit_form_id should not be sent for e-commerce events (purchase, add_to_cart).
- Both
googlesitekit_event_provider and googlesitekit_form_id should be added to the custom dimension definitions and valid-slug allowlists in both JS and PHP, so that the existing custom dimension creation and sync routes accept them.
- The implementation should follow the existing patterns used by
googlesitekit_post_author and googlesitekit_post_categories for tracking ID-based custom dimensions.
Implementation Brief
Event provider JS — googlesitekit_event_provider
Add the googlesitekit_event_provider parameter to every gtagEvent call across all 8 providers. The value must match the CONVERSION_EVENT_PROVIDER_SLUG defined in the provider's PHP class. Each provider file already has a known, fixed identity - hardcode the slug string in each file rather than introducing a shared JS constant
-
assets/js/event-providers/contact-form-7.js:
- Add
googlesitekit_event_provider: 'contact-form-7' to the event data object in the gtagEvent( 'contact', { ... } ) call.
-
assets/js/event-providers/woocommerce.js:
- Add
googlesitekit_event_provider: 'woocommerce' inside formatEventData() so it's included in every event returned by that function. For the purchase event which also uses formatEventData, this covers it automatically.
-
assets/js/event-providers/easy-digital-downloads.js:
- Two
gtagEvent call sites: add_to_cart on edd_cart_item_added and purchase on page load.
- Add
googlesitekit_event_provider: 'easy-digital-downloads' to both event data objects. For the add_to_cart call, add it to the object literal. For the purchase call, spread it into the data alongside currency and the purchase data.
-
assets/js/event-providers/wpforms.js:
- Add
googlesitekit_event_provider: 'wpforms' to the event data in the gtagEvent( 'submit_lead_form', ... ) call. Currently the second argument is either { user_data } or undefined — restructure to always pass an object: { googlesitekit_event_provider: 'wpforms', ...( userData ? { user_data: userData } : {} ) }.
-
assets/js/event-providers/ninja-forms.js:
- Same pattern as WPForms — add
googlesitekit_event_provider: 'ninja-forms' to the gtagEvent( 'submit_lead_form', ... ) call inside actionSubmit. Restructure to always pass an object.
-
assets/js/event-providers/mailchimp.js:
- Add
googlesitekit_event_provider: 'mailchimp' to the event data object in the gtagEvent( 'submit_lead_form', { ... } ) call. The object already exists (it has event_category), so just add the new property.
-
assets/js/event-providers/optin-monster.js:
- Add
googlesitekit_event_provider: 'optin-monster' to the eventData object in the gtagEvent( 'submit_lead_form', eventData ) call. The object already exists.
-
assets/js/event-providers/popup-maker.js:
- Add
googlesitekit_event_provider: 'popup-maker' to the gtagEvent( 'submit_lead_form', ... ) call inside the pum.integration.form.success handler. Restructure to always pass an object (same pattern as WPForms/Ninja Forms).
- Important note on Popup Maker deduplication: Popup Maker fires
pum.integration.form.success for all form submissions inside popups, but shouldHandleProvider() skips providers already handled by their own scripts (wpforms, contactform7, ninjaforms, mc4wp). This means when a WPForms form is submitted inside a Popup Maker popup, the event comes from wpforms.js with googlesitekit_event_provider: 'wpforms' — not from popup-maker.js. This is correct behavior and no changes are needed to the deduplication logic.
Event provider JS — googlesitekit_form_id
Add googlesitekit_form_id to lead generation event calls only (contact, submit_lead_form, generate_lead). Do not add it to e-commerce events (purchase, add_to_cart). Per provider, the form ID extraction approach:
-
assets/js/event-providers/contact-form-7.js:
- Form ID is already extracted in the current implementation as
event.detail.contactFormId (currently sent as event_category).
- Add
googlesitekit_form_id: String( event.detail.contactFormId ) to the event data object. The ID comes from the wpcf7_contact_form CPT.
-
assets/js/event-providers/wpforms.js:
- No arguments are passed to the
wpformsAjaxSubmitSuccess jQuery event — only event.target (the form element) is available.
- Extract form ID from the form element's data attribute:
event.target.dataset.formid.
- Add
googlesitekit_form_id: String( event.target.dataset.formid ) to the event data object. Guard with a check - only include if event.target.dataset.formid is truthy.
-
assets/js/event-providers/ninja-forms.js:
- The
submit:response callback receives an event object with event.data.form_id — this is the ID of the submitted form, stored in the custom table {prefix}_nf3_forms.
- Add
googlesitekit_form_id: String( event.data.form_id ) to the event data object inside actionSubmit. Guard with a check — only include if event.data.form_id is truthy.
-
assets/js/event-providers/mailchimp.js:
- The
subscribed callback receives mc4wpForm as the first argument. It exposes mc4wpForm.id (the form post ID from the mc4wp-form CPT).
- Add
googlesitekit_form_id: String( mc4wpForm.id ) to the event data object.
-
assets/js/event-providers/optin-monster.js:
detail.Campaign holds the campaign data. detail.Campaign.id is already captured in the current implementation as campaignID.
- Add
googlesitekit_form_id: String( detail.Campaign.id ) to the event data object.
-
assets/js/event-providers/popup-maker.js:
- The
pum.integration.form.success callback receives ( form, args ). The args object contains args.popupId — the ID of the popup CPT (post_type=popup).
- Add
googlesitekit_form_id: String( args.popupId ) to the event data object. Guard with a check — only include if args.popupId is truthy.
- Note:
args also contains formId and formProvider, but formId refers to the embedded form plugin's ID (e.g. a WPForms form ID), not the popup itself. Since Popup Maker's shouldHandleProvider() already skips events from known providers (WPForms, CF7, Ninja Forms, MC4WP), any event that reaches this handler is for an unknown/generic form inside a popup — so args.popupId is the appropriate identifier.
Test Coverage
-
Update includes/Modules/Analytics_4/Custom_Dimensions_Data_Available PHP tests (if they exist):
- Verify
is_valid_custom_dimension() returns true for googlesitekit_event_provider and googlesitekit_form_id.
- Verify
get_data_availability() includes both new slugs.
-
Update includes/Modules/Analytics_4/Report/RequestHelpers PHP tests:
- Verify
validate_shared_dimensions() accepts customEvent:googlesitekit_event_provider and customEvent:googlesitekit_form_id without throwing.
-
Update JS datastore tests in assets/js/modules/analytics-4/datastore/custom-dimensions.test.js:
- Verify that
CUSTOM_DIMENSION_DEFINITIONS includes both new dimension keys.
- Verify that creation/sync flows handle the new dimensions correctly (no behavioral changes expected — they go through the same
fetchCreateCustomDimension path).
QA Brief
Changelog entry
- Add new dimensions for events using Event Providers in Extended Conversion Tracking.
Feature Description
Building on the existing conversion event tracking infrastructure introduced in the Initial Conversion Event Infrastructure epic, this issue extends Site Kit's event providers (
assets/js/event-providers) to send two new custom dimensions alongside the conversion events they already track:googlesitekit_event_provider— identifies the plugin source of a tracked event (e.g. WooCommerce, Contact Form 7). This enables the Source Tabs in the Online Store Performance widget and the Info Icons on Form tabs in the Lead Generation Performance widget.googlesitekit_form_id— the ID of the form that triggered a lead generation event. Following the existing pattern ofgooglesitekit_post_authorandgooglesitekit_post_category, only the form ID is tracked (not the title), as the title can be queried fromwp_postsat reporting time. See Conversion Providers Form ID extraction for the spike findings on form ID extraction per provider.Both new custom dimensions must also be added to the existing custom dimension definitions and valid-slug allowlists in JS and PHP so existing routes accept and track them correctly.
Acceptance criteria
assets/js/event-providers), thegooglesitekit_event_providercustom dimension should be included in the event payload, with a value identifying the specific plugin source (e.g."woocommerce","contact-form-7").submit_lead_form,contact, orgenerate_lead), thegooglesitekit_form_idcustom dimension should also be included in the event payload, containing the integer or string ID of the form that was submitted.googlesitekit_form_idshould not be sent for e-commerce events (purchase,add_to_cart).googlesitekit_event_providerandgooglesitekit_form_idshould be added to the custom dimension definitions and valid-slug allowlists in both JS and PHP, so that the existing custom dimension creation and sync routes accept them.googlesitekit_post_authorandgooglesitekit_post_categoriesfor tracking ID-based custom dimensions.Implementation Brief
* In
assets/js/modules/analytics-4/datastore/constants.js, add two new entries toCUSTOM_DIMENSION_DEFINITIONSforgooglesitekit_form_idandgooglesitekit_event_provider, both scoped forEVENTCUSTOM_DIMENSION_DEFINITIONSkeyed object and will automatically be picked up by creation/sync flows that reference it.In
includes/Modules/Analytics_4/Custom_Dimensions_Data_Available.php, add'googlesitekit_event_provider'and'googlesitekit_form_id'to theCUSTOM_DIMENSION_SLUGSconstant array.is_valid_custom_dimension()check used bySave_Custom_Dimension_Data_Availableto accept these slugs, and includes them inget_data_availability().In
includes/Modules/Analytics_4/Report/RequestHelpers.php, add'customEvent:googlesitekit_event_provider'and'customEvent:googlesitekit_form_id'to the$valid_dimensionsarray insidevalidate_shared_dimensions().Include the 2 new dimensions to the
REQUIRED_CUSTOM_DIMENSIONSif Add Custom Dimensions setup in Analytics Settings #12738 has been merged before this issueEvent provider JS —
googlesitekit_event_providerAdd the
googlesitekit_event_providerparameter to everygtagEventcall across all 8 providers. The value must match theCONVERSION_EVENT_PROVIDER_SLUGdefined in the provider's PHP class. Each provider file already has a known, fixed identity - hardcode the slug string in each file rather than introducing a shared JS constantassets/js/event-providers/contact-form-7.js:googlesitekit_event_provider: 'contact-form-7'to the event data object in thegtagEvent( 'contact', { ... } )call.assets/js/event-providers/woocommerce.js:googlesitekit_event_provider: 'woocommerce'insideformatEventData()so it's included in every event returned by that function. For thepurchaseevent which also usesformatEventData, this covers it automatically.assets/js/event-providers/easy-digital-downloads.js:gtagEventcall sites:add_to_cartonedd_cart_item_addedandpurchaseon page load.googlesitekit_event_provider: 'easy-digital-downloads'to both event data objects. For theadd_to_cartcall, add it to the object literal. For thepurchasecall, spread it into the data alongside currency and the purchase data.assets/js/event-providers/wpforms.js:googlesitekit_event_provider: 'wpforms'to the event data in thegtagEvent( 'submit_lead_form', ... )call. Currently the second argument is either{ user_data }orundefined— restructure to always pass an object:{ googlesitekit_event_provider: 'wpforms', ...( userData ? { user_data: userData } : {} ) }.assets/js/event-providers/ninja-forms.js:googlesitekit_event_provider: 'ninja-forms'to thegtagEvent( 'submit_lead_form', ... )call insideactionSubmit. Restructure to always pass an object.assets/js/event-providers/mailchimp.js:googlesitekit_event_provider: 'mailchimp'to the event data object in thegtagEvent( 'submit_lead_form', { ... } )call. The object already exists (it hasevent_category), so just add the new property.assets/js/event-providers/optin-monster.js:googlesitekit_event_provider: 'optin-monster'to theeventDataobject in thegtagEvent( 'submit_lead_form', eventData )call. The object already exists.assets/js/event-providers/popup-maker.js:googlesitekit_event_provider: 'popup-maker'to thegtagEvent( 'submit_lead_form', ... )call inside thepum.integration.form.successhandler. Restructure to always pass an object (same pattern as WPForms/Ninja Forms).pum.integration.form.successfor all form submissions inside popups, butshouldHandleProvider()skips providers already handled by their own scripts (wpforms, contactform7, ninjaforms, mc4wp). This means when a WPForms form is submitted inside a Popup Maker popup, the event comes fromwpforms.jswithgooglesitekit_event_provider: 'wpforms'— not frompopup-maker.js. This is correct behavior and no changes are needed to the deduplication logic.Event provider JS —
googlesitekit_form_idAdd
googlesitekit_form_idto lead generation event calls only (contact,submit_lead_form,generate_lead). Do not add it to e-commerce events (purchase,add_to_cart). Per provider, the form ID extraction approach:assets/js/event-providers/contact-form-7.js:event.detail.contactFormId(currently sent asevent_category).googlesitekit_form_id: String( event.detail.contactFormId )to the event data object. The ID comes from thewpcf7_contact_formCPT.assets/js/event-providers/wpforms.js:wpformsAjaxSubmitSuccessjQuery event — onlyevent.target(the form element) is available.event.target.dataset.formid.googlesitekit_form_id: String( event.target.dataset.formid )to the event data object. Guard with a check - only include ifevent.target.dataset.formidis truthy.assets/js/event-providers/ninja-forms.js:submit:responsecallback receives aneventobject withevent.data.form_id— this is the ID of the submitted form, stored in the custom table{prefix}_nf3_forms.googlesitekit_form_id: String( event.data.form_id )to the event data object insideactionSubmit. Guard with a check — only include ifevent.data.form_idis truthy.assets/js/event-providers/mailchimp.js:subscribedcallback receivesmc4wpFormas the first argument. It exposesmc4wpForm.id(the form post ID from themc4wp-formCPT).googlesitekit_form_id: String( mc4wpForm.id )to the event data object.assets/js/event-providers/optin-monster.js:detail.Campaignholds the campaign data.detail.Campaign.idis already captured in the current implementation ascampaignID.googlesitekit_form_id: String( detail.Campaign.id )to the event data object.assets/js/event-providers/popup-maker.js:pum.integration.form.successcallback receives( form, args ). Theargsobject containsargs.popupId— the ID of the popup CPT (post_type=popup).googlesitekit_form_id: String( args.popupId )to the event data object. Guard with a check — only include ifargs.popupIdis truthy.argsalso containsformIdandformProvider, butformIdrefers to the embedded form plugin's ID (e.g. a WPForms form ID), not the popup itself. Since Popup Maker'sshouldHandleProvider()already skips events from known providers (WPForms, CF7, Ninja Forms, MC4WP), any event that reaches this handler is for an unknown/generic form inside a popup — soargs.popupIdis the appropriate identifier.Test Coverage
Update
includes/Modules/Analytics_4/Custom_Dimensions_Data_AvailablePHP tests (if they exist):is_valid_custom_dimension()returnstrueforgooglesitekit_event_providerandgooglesitekit_form_id.get_data_availability()includes both new slugs.Update
includes/Modules/Analytics_4/Report/RequestHelpersPHP tests:validate_shared_dimensions()acceptscustomEvent:googlesitekit_event_providerandcustomEvent:googlesitekit_form_idwithout throwing.Update JS datastore tests in
assets/js/modules/analytics-4/datastore/custom-dimensions.test.js:CUSTOM_DIMENSION_DEFINITIONSincludes both new dimension keys.fetchCreateCustomDimensionpath).QA Brief
Changelog entry