This commit is contained in:
2026-07-02 15:54:39 -06:00
commit 9883323161
17470 changed files with 4470592 additions and 0 deletions
@@ -0,0 +1,326 @@
( function ( GF_Google_Analytics_Admin, $ ) {
function display_error( message ) {
$( '.gforms_note_error' ).remove();
$( '#gform-page-loader-mask' ).hide();
$( '#gform-settings' ).before( '<div class="alert gforms_note_error" role="alert">' + message + '</div>' );
$( '.alert' ).get(0).scrollIntoView();
}
function hide_error() {
$( '.gforms_note_error' ).remove();
}
jQuery( document ).ready( function() {
// Main form wrapper.
let $form = $( '#gform-settings' );
// Handle disconnects from the admin.
let $disconnect = $( '.gfga-disconnect' );
if ( $disconnect.length > 0 ) {
$disconnect.on( 'click', function( e ) {
e.preventDefault();
$disconnect.html( google_analytics_admin_strings.disconnect );
var url_params = wpAjax.unserialize( e.target.href );
var nonce_value = url_params.nonce;
// Perform Ajax request.
$.post(
ajaxurl,
{
action: 'disconnect_account',
nonce: nonce_value,
},
function( response ) {
window.location.href = window.location.href;
}
);
} );
}
// Disable submit button and only reenable if required fields are filled out. Necessary to work with new loader.
let $action = $form.find( 'input[name="gfgaaction"]');
if ( $action.length !== 0 && $action.val() !== 'manual' ) {
let $submit_button = $form.find( ':submit' );
$submit_button.prop( 'disabled', true );
}
$( '#gform-settings-section-google-analytics-settings' ).on( 'change', ( 'input, select' ), function( event ) {
let property = $form.find( 'select[name="gaproperty"]' ).find(':selected').val();
let measurement_id = $( '#ga-data-streams select :selected' ).val();
let gtm_container = $form.find( 'select[name="gtmproperty"]' ).find( ':selected' ).val();
if ( ! gtm_container ) {
gtm_container = $form.find( '#container' ).val();
}
let workspace = $form.find( 'select[name="gaworkspace"]' ).val();
if ( ! workspace ) {
workspace = $form.find( '#workspace' ).val();
}
let $submit_button = $form.find( ':submit' );
if ( 'ga' === $action.val() ) {
if ( property && measurement_id ) {
$submit_button.prop( 'disabled', false );
} else {
$submit_button.prop( 'disabled', true );
}
}
if ( 'gtm' === $action.val() ) {
if ( gtm_container && workspace ) {
$submit_button.prop( 'disabled', false );
} else {
$submit_button.prop( 'disabled', true );
}
}
})
// Handle form submission on connect screen
$form.on( 'submit', function( e ) {
// Hide error message if there is one being displayed
hide_error();
// Determining if we're just connecting for the first time.
if ( $form.find( 'input[value="google_analytics_setup"]' ).length === 1 ) {
// is_postback
e.preventDefault();
// Set l18n.
var $save_button = $form.find( '#gform-settings-save' );
var $mode = $form.find( '[name="_gform_setting_mode"]:checked').val();
// Validate that a connection type was selected.
if ( ! $mode ) {
display_error( google_analytics_admin_strings.mode_required );
return;
}
$save_button.prop( 'value', google_analytics_admin_strings.redirect ).prop( 'disabled', 'disabled' );
// Get nonce.
var nonce_value = $form.find( 'input[name="gfganonce"]').val();
// Perform Ajax request.
$.post(
ajaxurl,
{
action: 'redirect_to_api',
nonce: nonce_value,
mode: $mode,
},
function( response ) {
if ( ! response.data.errors ) {
window.location.href = response.data.redirect;
}
},
'json'
);
return;
}
// Determine if we're executing in the correct form
let $action = $form.find( 'input[name="gfgaaction"]');
if( $action.length === 0 ) {
return;
}
if ( 'ga' === $action.val() ) {
e.preventDefault();
// Getting selected items from the account/property and data stream drop downs.
let $selected_property = $form.find( 'select[name="gaproperty"]' ).find( ':selected' );
let $selected_data_stream = $form.find( '#ga-data-streams select :selected' )
$.post(
ajaxurl,
{
action: 'save_google_analytics_data',
account_id: $selected_property.data( 'account-id' ),
account_name: $selected_property.data('account-name'),
property_id: $selected_property.val(),
property_name: $selected_property.data('property-name'),
measurement_id: $selected_data_stream.val(),
data_stream_name: $selected_data_stream.data( 'data-stream-name' ),
data_stream_id: $selected_data_stream.data( 'data-stream-id' ),
nonce: $form.find( 'input[name="gfganonce"]' ).val(),
token: $form.find('input[name="gfga_token"]' ).val(),
refresh: $form.find('input[name="gfga_refresh"]' ).val(),
},
function( response ) {
if ( response.success ) {
window.location.href = response['data'];
} else {
display_error( response.data[0].message );
}
}
);
}
if ( 'gtm' === $action.val() ) {
// We're in Google Tag Manager mode
e.preventDefault();
// Get Google Analytics data
let $selected_property = $form.find( 'select[name="gaproperty"]' ).find( ':selected' );
let $selected_data_stream = $form.find( '#ga-data-streams select :selected' )
// Get GTM Data
let $selected_gtm_account = $form.find( 'select[name="gtmproperty"] :selected' );
let $selected_gtm_container = $form.find( 'select[name="gacontainer"] :selected' );
let $gtm_workspace = $form.find( 'select[name="gaworkspace"] :selected' );
let $gtm_auto_create = $form.find( 'input[name="_gform_setting_gtm_auto_create"]' );
$.post(
ajaxurl,
{
action : 'save_google_tag_manager_data',
account_id : $selected_property.data( 'account-id' ),
account_name : $selected_property.data( 'account-name' ),
property_id : $selected_property.val(),
property_name : $selected_property.data( 'property-name' ),
measurement_id : $selected_data_stream.val(),
data_stream_name : $selected_data_stream.data( 'data-stream-name' ),
gtm_account_id : $selected_gtm_account.data( 'account-id' ),
gtm_account_name : $selected_gtm_account.val(),
gtm_api_path : $selected_gtm_container.data( 'path' ),
gtm_container : $selected_gtm_container.val(),
gtm_auto_create : $gtm_auto_create.val(),
gtm_workspace_id : $gtm_workspace.val(),
gtm_workspace_name : $gtm_workspace.text(),
nonce : $form.find( 'input[name="gfganonce"]' ).val(),
token : $form.find( 'input[name="gfga_token"]' ).val(),
refresh : $form.find( 'input[name="gfga_refresh"]' ).val(),
},
function( response ) {
if ( false === response.success ) {
display_error( response.data[0].message );
} else {
window.location.href = response.data;
}
}
);
}
if ( 'manual' === $action.val() ) {
// We're in manual configuration mode
e.preventDefault();
$.post(
ajaxurl,
{
action : 'save_manual_configuration_data',
mode : $form.find( '#ga_connection_type' ).val(),
measurement_id : $form.find( '#ga_measurement_id' ).val(),
gmp_api_secret : $form.find( '#gmp_api_secret' ).val(),
gtm_container : $form.find( '#gtm_container_id' ).val(),
gtm_workspace_id : $form.find( '#gtm_workspace_id' ).val(),
nonce : $form.find( 'input[name="gfganonce"]' ).val(),
ga : $form.find( 'input[name="_gform_setting_ga"]:checked' ).val(),
install_gtm : $form.find('input[name="_gform_setting_install_gtm"]:checked').val(),
ua_tracker : $form.find('input[name="_gform_setting_ua_tracker"]').val(),
},
function( response ) {
if ( false === response.success ) {
display_error( response.data[0].message );
} else {
window.location.href = response.data;
}
}
);
}
} );
// Get data streams for selected Analytics account/property.
$( '#gaproperty' ).on( 'change', function( e ) {
// Hide error message if there is one being displayed
hide_error();
let $option = $( this ).find( ':selected' );
let nonce = $( 'body' ).find( 'input[name="gfganonce"]' ).val();
let token = $form.find('input[name="gfga_token"]' ).val();
$( '#ga-data-streams' ).html( '<br /><img src="' + google_analytics_admin_strings.spinner + '" />' );
$.post(
ajaxurl,
{
action: 'get_ga4_data_streams',
account: $option.data( 'account-id' ),
property: $option.val(),
nonce: nonce,
token: token,
},
function( response ) {
if ( response.success ) {
$( '#ga-data-streams' ).html( response['data'] );
} else {
$( '#ga-data-streams' ).html( '' );
display_error( response.data[0].message );
}
}
);
} );
// Get containers for selected GTM account.
$( '#gtmproperty' ).on( 'change', function( e ) {
// Hide error message if there is one being displayed
hide_error();
const $option = $( this ).find( ':selected' );
const accountId = $option.data( 'accountId' );
const path = $option.data( 'path' );
const token = $option.data( 'token' );
const nonce = $( 'body' ).find( 'input[name="gfganonce"]' ).val();
$( '#gtm-containers' ).html( '<br /><img src="' + google_analytics_admin_strings.spinner + '" />' );
$( '#gtm-workspaces' ).html( '' );
$.post(
ajaxurl,
{
action: 'get_gtm_containers',
accountId: accountId,
path: path,
nonce: nonce,
token: token,
},
function( response ) {
if( response.success ) {
$( '#gtm-containers' ).html( response.body );
} else {
display_error( response.data[0].message );
$( '#gtm-containers' ).html( '' );
}
}
);
} );
// Get views for selected UA account.
$( document ).on( 'change', '#gacontainer', function( e ) {
// Hide error message if there is one being displayed
hide_error();
const $option = $( this ).find( ':selected' );
const path = $option.data( 'path' );
const token = $option.data( 'token' );
const nonce = $( 'body' ).find( 'input[name="gfganonce"]' ).val();
$( '#gtm-workspaces' ).html( '<br /><img src="' + google_analytics_admin_strings.spinner + '" />' );
$.post(
ajaxurl,
{
action: 'get_gtm_workspaces',
path: path,
nonce: nonce,
token: token,
},
function( response ) {
if( response.success ) {
$( '#gtm-workspaces' ).html( response.body );
} else {
display_error( response.data[0].message );
$( '#gform_setting_workspace' ).show();
$( '#gtm-workspaces' ).html( '' );
}
}
);
} );
} );
}( window.GF_Google_Analytics_Admin = window.GF_Google_Analytics_Admin || {}, jQuery ) );
File diff suppressed because one or more lines are too long
@@ -0,0 +1,289 @@
( function () {
/**
* Send events to Google Analytics. Use Ajax call so no duplicate entries are recorded.
*
* @since 1.3.0
*
* @param {number} entryId The entry ID associated with this submission.
* @param {number} feedId The feed ID associated with this event.
* @param {array} parameters Event parameters to send to Google Analytics.
* @param {string} eventName Event name to be sent to Google Analytics.
*/
this.send_unique_to_ga = async function ( entryId, feedId, parameters, eventName ) {
let has_sent = await this.has_sent_feed( entryId, feedId );
if ( ! has_sent ) {
this.send_to_ga( parameters, eventName );
this.mark_feed_as_sent( entryId, feedId );
}
this.maybe_trigger_feeds_sent();
};
/**
* Send events to Google Analytics. Use ajax call so no duplicate entries are recorded.
*
* @since 1.0.0
* @param {array} parameters Event parameters to send to Google Analytics.
* @param {string} eventName Event name to be sent to Google Analytics.
*/
this.send_to_ga = function( parameters, eventName ) {
const eventTracker = gforms_google_analytics_frontend_strings.ua_tracker;
// Check for gtab implementation
if ( typeof window.parent.gtag != 'undefined' ) {
window.parent.gtag( 'event', eventName, parameters );
} else {
// Check for GA from Monster Insights Plugin
if ( typeof window.parent.ga == 'undefined' ) {
if ( typeof window.parent.__gaTracker != 'undefined' ) {
window.parent.ga = window.parent.__gaTracker;
}
}
if ( typeof window.parent.ga != 'undefined' ) {
let ga_send = 'send';
// Try to get original UA code from third-party plugins or tag manager
if ( eventTracker.length > 0 ) {
ga_send = eventTracker + '.' + ga_send;
}
// Use that tracker
window.parent.ga( ga_send, eventName, parameters );
} else {
console.error( 'Google Tag Manger script is not active. You may need to enable "Output the Google Analytics Script" setting on the Forms -> Settings -> Google Analytics page');
return;
}
}
// Logging if enabled.
const eventData = { 'type': 'ga', 'eventName' : eventName, 'parameters' : parameters };
this.consoleLog('Google Analytics event sent. Event data: ');
this.consoleLog( JSON.stringify( eventData, null, 2 ) );
// Triggering event_sent event.
this.trigger_event( 'googleanalytics/event_sent', eventData );
jQuery.post(
gforms_google_analytics_frontend_strings.ajaxurl,
{
action: 'gf_ga_log_event_sent',
parameters: parameters,
eventName: eventName,
connection: 'ga',
nonce: gforms_google_analytics_frontend_strings.logging_nonce,
}
);
}
/**
* Send events to Google Tag Manager.
*
* @since 1.3.0
*
* @param {number} entryId The entry ID associated with this submission.
* @param {number} feedId The feed ID associated with this event.
* @param {array} parameters Event parameters to send to Google Analytics.
* @param {string} triggerName Event type to be sent to Google Analytics.
*/
this.send_unique_to_gtm = async function( entryId, feedId, parameters, triggerName) {
let has_sent = await this.has_sent_feed( entryId, feedId );
if ( ! has_sent ) {
this.send_to_gtm( parameters, triggerName );
this.mark_feed_as_sent( entryId, feedId );
} else {
this.consoleLog( 'Event has already been sent. Aborting... Entry id: ' + entryId + '. Feed Id: ' + feedId );
}
this.maybe_trigger_feeds_sent();
}
/**
* Send events to Google Tag Manager.
*
* @since 1.0.0
*
* @param {array} parameters Event parameters to send to Google Analytics.
* @param {string} triggerName Event name to be sent to Google Tag Manger.
*/
this.send_to_gtm = function( parameters, triggerName) {
if ( typeof ( window.parent.dataLayer ) == 'undefined' ) {
console.error( 'Google Tag Manger script is not active. You may need to enable "Output the Google Tag Manager Script" setting on the Forms -> Settings -> Google Analytics page' );
return;
}
parameters['event'] = triggerName;
window.parent.dataLayer.push( parameters );
// Logging if enabled.
const eventData = { 'type': 'gtm', 'triggerName' : triggerName, 'parameters' : parameters };
this.consoleLog('Google Analytics event sent. Event data: ');
this.consoleLog( JSON.stringify( eventData, null, 2 ) );
// Triggering event_sent event.
this.trigger_event( 'googleanalytics/event_sent', eventData );
jQuery.post(
gforms_google_analytics_frontend_strings.ajaxurl,
{
action: 'gf_ga_log_event_sent',
parameters: parameters,
triggerName: triggerName,
connection: 'gtm',
nonce: gforms_google_analytics_frontend_strings.logging_nonce,
}
);
}
/**
* Determines if event for this entry and feed has already been sent.
*
* @since 1.3.0
*
* @param {number} entryId Current entry id.
* @param {number} feedId Current feed id.
*
* @returns {bool} Returns true if the event for this entry and feed has already been sent. Returns false if not.
*/
this.has_sent_feed = async function( entryId, feedId ) {
let response = await jQuery.post( gforms_google_analytics_frontend_strings.ajaxurl, { action: 'get_entry_meta', entry_id: entryId, feed_id: feedId, nonce: gforms_google_analytics_frontend_strings.nonce }, 'json' );
return response.data.event_sent;
}
/**
* Mark an event as sent via AJAX. Part of the system to prevent duplicate events from being sent.
*
* @since 1.3.0
*
* @param {number} entryId Current entry id.
* @param {number} feedId Current feed id.
*/
this.mark_feed_as_sent = function( entryId, feedId ) {
jQuery.post( gforms_google_analytics_frontend_strings.ajaxurl, { action: 'save_entry_meta', entry_id: entryId, feed_id: feedId, nonce: gforms_google_analytics_frontend_strings.nonce } );
}
/**
* Holds the number of feeds that have been sent.
*
* @since 1.3.0
*
* @type {number}
*/
this.feeds_sent = 0;
/**
* Triggers 'googleanalytics/all_events_sent' after the last feed has been sent.
*
* @since 1.3.0
*/
this.maybe_trigger_feeds_sent = function() {
this.feeds_sent++;
this.consoleLog( 'Google Analytics event successfully sent: ' + this.feeds_sent + ' of ' + window['ga_feed_count'] );
if ( this.feeds_sent >= window['ga_feed_count'] ) {
this.consoleLog( 'All Google Analytics events have been sent.' );
// All feeds have been sent. Trigger feeds sent event.
this.trigger_event( 'googleanalytics/all_events_sent' );
window['all_ga_events_sent'] = true;
// Reset counters.
this.feeds_sent = 0;
window['ga_feed_count'] = 0;
}
}
/**
* Triggers a Javascript event.
*
* @since 1.3.0
*
* @param {string} eventName Name of the event.
* @param {*} eventData Data associated with this event.
*/
this.trigger_event = function( eventName, eventData ) {
const event = new CustomEvent( eventName, { detail: eventData } );
window.dispatchEvent( event );
}
/**
* Logs to the console if logging is enabled in settings page.
*
* @since 1.3.0
*
* @param {*} message The message to be logged.
*/
this.consoleLog = function( message ) {
if ( gforms_google_analytics_frontend_strings.logging_enabled !== '1' ) {
return;
}
console.log( message );
}
this.handle_ajax_feeds = async function( data ) {
if ( ! data?.submissionResult?.data?.ajax_feeds ) {
return data;
}
for ( const feed of data.submissionResult.data.ajax_feeds ) {
if ( feed?.mode == 'ga' ) {
this.send_unique_to_ga( data.submissionResult.data.entry_id, feed.feed_id, feed.parameters, feed.eventName );
}
if ( feed?.mode == 'gtm' ) {
this.send_unique_to_gtm( data.submissionResult.data.entry_id, feed.feed_id, feed.parameters, feed.eventName );
}
window.parent[ 'ga_feed_count' ] = window.parent[ 'ga_feed_count' ] ? window.parent[ 'ga_feed_count' ] + 1 : 1;
}
}
this.handle_ajax_pagination = function( data ) {
if ( ! data?.submissionResult?.data?.ajax_pagination ) {
return data;
}
const ajaxPagination = data?.submissionResult?.data?.ajax_pagination
if ( ajaxPagination?.mode == 'ga' ) {
window.parent.GF_Google_Analytics.send_to_ga( ajaxPagination.parameters, ajaxPagination.eventName );
}
if ( ajaxPagination?.mode == 'gtm' ) {
window.parent.GF_Google_Analytics.send_to_gtm( ajaxPagination.parameters, ajaxPagination.eventName );
}
this.consoleLog( 'Pagination event has been sent.' );
return data;
}
/**
* Initializes this object.
*/
this.init = function() {
window.GF_Google_Analytics = this;
let ajaxFilterRegistered = false;
// Trigger script loaded event
this.trigger_event( 'googleanalytics/script_loaded' );
document.addEventListener( 'gform/post_render', ( ) => {
if ( ajaxFilterRegistered ) {
return;
}
window.gform.utils.addFilter( 'gform/ajax/post_ajax_submission', ( data ) => {
this.handle_ajax_feeds( data );
this.handle_ajax_pagination( data );
return data;
} );
ajaxFilterRegistered = true;
} );
}
this.init();
}() );
@@ -0,0 +1 @@
!function(){this.send_unique_to_ga=async function(e,t,n,s){await this.has_sent_feed(e,t)||(this.send_to_ga(n,s),this.mark_feed_as_sent(e,t)),this.maybe_trigger_feeds_sent()},this.send_to_ga=function(t,n){var s=gforms_google_analytics_frontend_strings.ua_tracker;if(void 0!==window.parent.gtag)window.parent.gtag("event",n,t);else{if(void 0===window.parent.ga&&void 0!==window.parent.__gaTracker&&(window.parent.ga=window.parent.__gaTracker),void 0===window.parent.ga)return void console.error('Google Tag Manger script is not active. You may need to enable "Output the Google Analytics Script" setting on the Forms -> Settings -> Google Analytics page');{let e="send";0<s.length&&(e=s+"."+e),window.parent.ga(e,n,t)}}s={type:"ga",eventName:n,parameters:t};this.consoleLog("Google Analytics event sent. Event data: "),this.consoleLog(JSON.stringify(s,null,2)),this.trigger_event("googleanalytics/event_sent",s),jQuery.post(gforms_google_analytics_frontend_strings.ajaxurl,{action:"gf_ga_log_event_sent",parameters:t,eventName:n,connection:"ga",nonce:gforms_google_analytics_frontend_strings.logging_nonce})},this.send_unique_to_gtm=async function(e,t,n,s){await this.has_sent_feed(e,t)?this.consoleLog("Event has already been sent. Aborting... Entry id: "+e+". Feed Id: "+t):(this.send_to_gtm(n,s),this.mark_feed_as_sent(e,t)),this.maybe_trigger_feeds_sent()},this.send_to_gtm=function(e,t){var n;void 0===window.parent.dataLayer?console.error('Google Tag Manger script is not active. You may need to enable "Output the Google Tag Manager Script" setting on the Forms -> Settings -> Google Analytics page'):(e.event=t,window.parent.dataLayer.push(e),n={type:"gtm",triggerName:t,parameters:e},this.consoleLog("Google Analytics event sent. Event data: "),this.consoleLog(JSON.stringify(n,null,2)),this.trigger_event("googleanalytics/event_sent",n),jQuery.post(gforms_google_analytics_frontend_strings.ajaxurl,{action:"gf_ga_log_event_sent",parameters:e,triggerName:t,connection:"gtm",nonce:gforms_google_analytics_frontend_strings.logging_nonce}))},this.has_sent_feed=async function(e,t){return(await jQuery.post(gforms_google_analytics_frontend_strings.ajaxurl,{action:"get_entry_meta",entry_id:e,feed_id:t,nonce:gforms_google_analytics_frontend_strings.nonce},"json")).data.event_sent},this.mark_feed_as_sent=function(e,t){jQuery.post(gforms_google_analytics_frontend_strings.ajaxurl,{action:"save_entry_meta",entry_id:e,feed_id:t,nonce:gforms_google_analytics_frontend_strings.nonce})},this.feeds_sent=0,this.maybe_trigger_feeds_sent=function(){this.feeds_sent++,this.consoleLog("Google Analytics event successfully sent: "+this.feeds_sent+" of "+window.ga_feed_count),this.feeds_sent>=window.ga_feed_count&&(this.consoleLog("All Google Analytics events have been sent."),this.trigger_event("googleanalytics/all_events_sent"),window.all_ga_events_sent=!0,this.feeds_sent=0,window.ga_feed_count=0)},this.trigger_event=function(e,t){e=new CustomEvent(e,{detail:t});window.dispatchEvent(e)},this.consoleLog=function(e){"1"===gforms_google_analytics_frontend_strings.logging_enabled&&console.log(e)},this.handle_ajax_feeds=async function(e){if(!e?.submissionResult?.data?.ajax_feeds)return e;for(var t of e.submissionResult.data.ajax_feeds)"ga"==t?.mode&&this.send_unique_to_ga(e.submissionResult.data.entry_id,t.feed_id,t.parameters,t.eventName),"gtm"==t?.mode&&this.send_unique_to_gtm(e.submissionResult.data.entry_id,t.feed_id,t.parameters,t.eventName),window.parent.ga_feed_count=window.parent.ga_feed_count?window.parent.ga_feed_count+1:1},this.handle_ajax_pagination=function(e){var t;return e?.submissionResult?.data?.ajax_pagination&&("ga"==(t=e?.submissionResult?.data?.ajax_pagination)?.mode&&window.parent.GF_Google_Analytics.send_to_ga(t.parameters,t.eventName),"gtm"==t?.mode&&window.parent.GF_Google_Analytics.send_to_gtm(t.parameters,t.eventName),this.consoleLog("Pagination event has been sent.")),e},this.init=function(){window.GF_Google_Analytics=this;let e=!1;this.trigger_event("googleanalytics/script_loaded"),document.addEventListener("gform/post_render",()=>{e||(window.gform.utils.addFilter("gform/ajax/post_ajax_submission",e=>(this.handle_ajax_feeds(e),this.handle_ajax_pagination(e),e)),e=!0)})},this.init()}();