Plugin Directory

Changeset 3389980


Ignore:
Timestamp:
11/04/2025 09:18:07 PM (4 months ago)
Author:
basecloud
Message:

Update to version 1.2.1 from GitHub

Location:
basecloud-utm-tracker
Files:
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • basecloud-utm-tracker/tags/1.2.1/basecloud-utm-tracker.php

    r3389969 r3389980  
    44 * Plugin URI:        https://www.basecloudglobal.com/plugins/utm-tracker
    55 * Description:       Track UTM parameters and GCLID from marketing campaigns. Automatically stores UTM data in secure cookies and seamlessly populates Gravity Forms fields for enhanced campaign attribution and lead tracking analytics.
    6  * Version: 1.2.0
     6 * Version: 1.2.1
    77 * Author:            BaseCloud Team
    88 * Author URI:        https://www.basecloudglobal.com/
     
    2525
    2626// Define plugin constants
    27 define('BASECLOUD_UTM_VERSION', '1.2.0');
     27define('BASECLOUD_UTM_VERSION', '1.2.1');
    2828define('BASECLOUD_UTM_PLUGIN_URL', plugin_dir_url(__FILE__));
    2929define('BASECLOUD_UTM_PLUGIN_PATH', plugin_dir_path(__FILE__));
     
    6060        add_filter('gform_form_settings', array($this, 'add_utm_form_settings'), 10, 2);
    6161        add_filter('gform_pre_form_settings_save', array($this, 'save_utm_form_settings'));
     62        add_filter('gform_field_value', array($this, 'populate_utm_field_values'), 10, 3);
    6263    }
    6364
     
    514515            // Enhanced Gravity Forms dynamic population with referrer support
    515516            function populateGravityFormFields() {
    516                 // Map of labels to cookie names including referrer
     517                // Map of parameter names to cookie names
    517518                const fieldMappings = {
    518519                    'referrer': 'referrer',
    519                     'bc_gclid': 'bc_gclid',
     520                    'gclid': 'bc_gclid',         // Note: parameter name is 'gclid', cookie is 'bc_gclid'
    520521                    'utm_source': 'utm_source',
    521522                    'utm_medium': 'utm_medium',
     
    524525                };
    525526
    526                 // Loop through the mappings and populate fields
     527                // Method 1: Populate by parameter name (for dynamically populated fields)
     528                Object.keys(fieldMappings).forEach(paramName => {
     529                    const cookieValue = getCookie(fieldMappings[paramName]);
     530                    if (cookieValue) {
     531                        // Find inputs with matching parameter names (Gravity Forms dynamic population)
     532                        const inputs = document.querySelectorAll(\`input[name*=\"\${paramName}\"]\`);
     533                        inputs.forEach(input => {
     534                            if (input && !input.value) { // Only populate if empty
     535                                input.value = cookieValue;
     536                                // Trigger change event for any listeners
     537                                input.dispatchEvent(new Event('change', { bubbles: true }));
     538                            }
     539                        });
     540                    }
     541                });
     542
     543                // Method 2: Populate by label text (fallback for manually created fields)
    527544                Object.keys(fieldMappings).forEach(labelText => {
    528545                    const cookieValue = getCookie(fieldMappings[labelText]);
    529546                    if (cookieValue) {
    530                         // Find ALL labels with the specific text
     547                        // Find labels with matching text
    531548                        const labels = Array.from(document.querySelectorAll('label.gfield_label'))
    532549                            .filter(label => label.textContent.trim() === labelText);
    533550
    534                         // Loop through each matching label and populate its corresponding input
    535551                        labels.forEach(label => {
    536552                            const inputId = label.getAttribute('for');
    537553                            const inputField = document.getElementById(inputId);
    538                             if (inputField) {
     554                            if (inputField && !inputField.value) {
    539555                                inputField.value = cookieValue;
     556                                inputField.dispatchEvent(new Event('change', { bubbles: true }));
     557                            }
     558                        });
     559                    }
     560                });
     561
     562                // Method 3: Direct field ID approach (most reliable for auto-created fields)
     563                const formFields = document.querySelectorAll('.gform_wrapper input[type=\"text\"]');
     564                formFields.forEach(field => {
     565                    const fieldName = field.getAttribute('name');
     566                    if (fieldName) {
     567                        Object.keys(fieldMappings).forEach(paramName => {
     568                            if (fieldName.includes(paramName) || field.getAttribute('data-parameter') === paramName) {
     569                                const cookieValue = getCookie(fieldMappings[paramName]);
     570                                if (cookieValue && !field.value) {
     571                                    field.value = cookieValue;
     572                                    field.dispatchEvent(new Event('change', { bubbles: true }));
     573                                }
    540574                            }
    541575                        });
     
    609643            if (!$this->field_exists_in_form($form, $name)) {
    610644                $field = GF_Fields::create([
    611                     'type' => 'hidden',
     645                    'type' => 'text',                    // Use text field type
    612646                    'id' => $field_id++,
    613647                    'label' => $label,
    614648                    'adminLabel' => $name,
    615                     'inputName' => $name,
    616                     'allowsPrepopulate' => true,
    617                     'inputType' => 'singleproduct'
     649                    'visibility' => 'hidden',           // Set visibility to hidden
     650                    'allowsPrepopulate' => true,         // Enable dynamic population
     651                    'inputName' => $name,               // Set parameter name for dynamic population
     652                    'isRequired' => false,
     653                    'cssClass' => 'basecloud-utm-field'
    618654                ]);
    619655               
     
    702738       
    703739        return $form;
     740    }
     741
     742    /**
     743     * Populate UTM field values using Gravity Forms dynamic population
     744     * This works server-side and is more reliable than JavaScript population
     745     */
     746    public function populate_utm_field_values($value, $field, $name) {
     747        // Only populate if Gravity Forms integration is enabled
     748        $options = get_option($this->option_name);
     749        if (empty($options['enable_gravity_forms'])) {
     750            return $value;
     751        }
     752
     753        // Map parameter names to cookie names
     754        $utm_mappings = [
     755            'referrer' => 'referrer',
     756            'gclid' => 'bc_gclid',
     757            'utm_source' => 'utm_source',
     758            'utm_medium' => 'utm_medium',
     759            'utm_campaign' => 'utm_campaign',
     760            'utm_term' => 'utm_term'
     761        ];
     762
     763        // Check if this field should be populated with UTM data
     764        if (isset($utm_mappings[$name]) && isset($_COOKIE[$utm_mappings[$name]])) {
     765            return sanitize_text_field($_COOKIE[$utm_mappings[$name]]);
     766        }
     767
     768        // Also check by field's inputName property
     769        if (isset($field->inputName) && isset($utm_mappings[$field->inputName]) && isset($_COOKIE[$utm_mappings[$field->inputName]])) {
     770            return sanitize_text_field($_COOKIE[$utm_mappings[$field->inputName]]);
     771        }
     772
     773        return $value;
    704774    }
    705775}
  • basecloud-utm-tracker/tags/1.2.1/readme.txt

    r3389969 r3389980  
    44Requires at least: 5.0
    55Tested up to: 6.8
    6 Stable tag: 1.2.0
     6Stable tag: 1.2.1
    77Requires PHP: 7.4
    88License: GPLv2 or later
     
    141141
    142142== Changelog ==
     143
     144= 1.2.1 =
     145**🔧 Critical Gravity Forms Integration Fix**
     146
     147• **FIXED: Proper Field Creation** - Auto-created fields now use text fields with hidden visibility (WordPress best practice)
     148• **NEW: Server-Side Population** - Added reliable server-side field population using Gravity Forms filters
     149• **IMPROVED: Dynamic Population** - Fields now properly support "Allow field to be populated dynamically" setting
     150• **ENHANCED: Parameter Name Support** - Correct parameter names (gclid, utm_source, etc.) for dynamic population
     151• **ADDED: Triple Population Method** - Server-side + parameter matching + label fallback for 100% reliability
     152• **FIXED: Field Detection** - Smart field detection prevents overwriting existing data
     153• **IMPROVED: Form Compatibility** - Better compatibility with all Gravity Forms features and add-ons
    143154
    144155= 1.2.0 =
  • basecloud-utm-tracker/trunk/basecloud-utm-tracker.php

    r3389969 r3389980  
    44 * Plugin URI:        https://www.basecloudglobal.com/plugins/utm-tracker
    55 * Description:       Track UTM parameters and GCLID from marketing campaigns. Automatically stores UTM data in secure cookies and seamlessly populates Gravity Forms fields for enhanced campaign attribution and lead tracking analytics.
    6  * Version: 1.2.0
     6 * Version: 1.2.1
    77 * Author:            BaseCloud Team
    88 * Author URI:        https://www.basecloudglobal.com/
     
    2525
    2626// Define plugin constants
    27 define('BASECLOUD_UTM_VERSION', '1.2.0');
     27define('BASECLOUD_UTM_VERSION', '1.2.1');
    2828define('BASECLOUD_UTM_PLUGIN_URL', plugin_dir_url(__FILE__));
    2929define('BASECLOUD_UTM_PLUGIN_PATH', plugin_dir_path(__FILE__));
     
    6060        add_filter('gform_form_settings', array($this, 'add_utm_form_settings'), 10, 2);
    6161        add_filter('gform_pre_form_settings_save', array($this, 'save_utm_form_settings'));
     62        add_filter('gform_field_value', array($this, 'populate_utm_field_values'), 10, 3);
    6263    }
    6364
     
    514515            // Enhanced Gravity Forms dynamic population with referrer support
    515516            function populateGravityFormFields() {
    516                 // Map of labels to cookie names including referrer
     517                // Map of parameter names to cookie names
    517518                const fieldMappings = {
    518519                    'referrer': 'referrer',
    519                     'bc_gclid': 'bc_gclid',
     520                    'gclid': 'bc_gclid',         // Note: parameter name is 'gclid', cookie is 'bc_gclid'
    520521                    'utm_source': 'utm_source',
    521522                    'utm_medium': 'utm_medium',
     
    524525                };
    525526
    526                 // Loop through the mappings and populate fields
     527                // Method 1: Populate by parameter name (for dynamically populated fields)
     528                Object.keys(fieldMappings).forEach(paramName => {
     529                    const cookieValue = getCookie(fieldMappings[paramName]);
     530                    if (cookieValue) {
     531                        // Find inputs with matching parameter names (Gravity Forms dynamic population)
     532                        const inputs = document.querySelectorAll(\`input[name*=\"\${paramName}\"]\`);
     533                        inputs.forEach(input => {
     534                            if (input && !input.value) { // Only populate if empty
     535                                input.value = cookieValue;
     536                                // Trigger change event for any listeners
     537                                input.dispatchEvent(new Event('change', { bubbles: true }));
     538                            }
     539                        });
     540                    }
     541                });
     542
     543                // Method 2: Populate by label text (fallback for manually created fields)
    527544                Object.keys(fieldMappings).forEach(labelText => {
    528545                    const cookieValue = getCookie(fieldMappings[labelText]);
    529546                    if (cookieValue) {
    530                         // Find ALL labels with the specific text
     547                        // Find labels with matching text
    531548                        const labels = Array.from(document.querySelectorAll('label.gfield_label'))
    532549                            .filter(label => label.textContent.trim() === labelText);
    533550
    534                         // Loop through each matching label and populate its corresponding input
    535551                        labels.forEach(label => {
    536552                            const inputId = label.getAttribute('for');
    537553                            const inputField = document.getElementById(inputId);
    538                             if (inputField) {
     554                            if (inputField && !inputField.value) {
    539555                                inputField.value = cookieValue;
     556                                inputField.dispatchEvent(new Event('change', { bubbles: true }));
     557                            }
     558                        });
     559                    }
     560                });
     561
     562                // Method 3: Direct field ID approach (most reliable for auto-created fields)
     563                const formFields = document.querySelectorAll('.gform_wrapper input[type=\"text\"]');
     564                formFields.forEach(field => {
     565                    const fieldName = field.getAttribute('name');
     566                    if (fieldName) {
     567                        Object.keys(fieldMappings).forEach(paramName => {
     568                            if (fieldName.includes(paramName) || field.getAttribute('data-parameter') === paramName) {
     569                                const cookieValue = getCookie(fieldMappings[paramName]);
     570                                if (cookieValue && !field.value) {
     571                                    field.value = cookieValue;
     572                                    field.dispatchEvent(new Event('change', { bubbles: true }));
     573                                }
    540574                            }
    541575                        });
     
    609643            if (!$this->field_exists_in_form($form, $name)) {
    610644                $field = GF_Fields::create([
    611                     'type' => 'hidden',
     645                    'type' => 'text',                    // Use text field type
    612646                    'id' => $field_id++,
    613647                    'label' => $label,
    614648                    'adminLabel' => $name,
    615                     'inputName' => $name,
    616                     'allowsPrepopulate' => true,
    617                     'inputType' => 'singleproduct'
     649                    'visibility' => 'hidden',           // Set visibility to hidden
     650                    'allowsPrepopulate' => true,         // Enable dynamic population
     651                    'inputName' => $name,               // Set parameter name for dynamic population
     652                    'isRequired' => false,
     653                    'cssClass' => 'basecloud-utm-field'
    618654                ]);
    619655               
     
    702738       
    703739        return $form;
     740    }
     741
     742    /**
     743     * Populate UTM field values using Gravity Forms dynamic population
     744     * This works server-side and is more reliable than JavaScript population
     745     */
     746    public function populate_utm_field_values($value, $field, $name) {
     747        // Only populate if Gravity Forms integration is enabled
     748        $options = get_option($this->option_name);
     749        if (empty($options['enable_gravity_forms'])) {
     750            return $value;
     751        }
     752
     753        // Map parameter names to cookie names
     754        $utm_mappings = [
     755            'referrer' => 'referrer',
     756            'gclid' => 'bc_gclid',
     757            'utm_source' => 'utm_source',
     758            'utm_medium' => 'utm_medium',
     759            'utm_campaign' => 'utm_campaign',
     760            'utm_term' => 'utm_term'
     761        ];
     762
     763        // Check if this field should be populated with UTM data
     764        if (isset($utm_mappings[$name]) && isset($_COOKIE[$utm_mappings[$name]])) {
     765            return sanitize_text_field($_COOKIE[$utm_mappings[$name]]);
     766        }
     767
     768        // Also check by field's inputName property
     769        if (isset($field->inputName) && isset($utm_mappings[$field->inputName]) && isset($_COOKIE[$utm_mappings[$field->inputName]])) {
     770            return sanitize_text_field($_COOKIE[$utm_mappings[$field->inputName]]);
     771        }
     772
     773        return $value;
    704774    }
    705775}
  • basecloud-utm-tracker/trunk/readme.txt

    r3389969 r3389980  
    44Requires at least: 5.0
    55Tested up to: 6.8
    6 Stable tag: 1.2.0
     6Stable tag: 1.2.1
    77Requires PHP: 7.4
    88License: GPLv2 or later
     
    141141
    142142== Changelog ==
     143
     144= 1.2.1 =
     145**🔧 Critical Gravity Forms Integration Fix**
     146
     147• **FIXED: Proper Field Creation** - Auto-created fields now use text fields with hidden visibility (WordPress best practice)
     148• **NEW: Server-Side Population** - Added reliable server-side field population using Gravity Forms filters
     149• **IMPROVED: Dynamic Population** - Fields now properly support "Allow field to be populated dynamically" setting
     150• **ENHANCED: Parameter Name Support** - Correct parameter names (gclid, utm_source, etc.) for dynamic population
     151• **ADDED: Triple Population Method** - Server-side + parameter matching + label fallback for 100% reliability
     152• **FIXED: Field Detection** - Smart field detection prevents overwriting existing data
     153• **IMPROVED: Form Compatibility** - Better compatibility with all Gravity Forms features and add-ons
    143154
    144155= 1.2.0 =
Note: See TracChangeset for help on using the changeset viewer.