A modern WordPress plugin for managing custom GA4-style DataLayer events. EventLayer provides a user-friendly interface for creating sophisticated event tracking rules that automatically inject JavaScript for Google Tag Manager and Google Analytics 4 integration.
- Native WordPress Integration: Uses custom post types for event rules with full revision history
- Advanced Event Configuration: Define event types, triggers, and parameters
- Dynamic Parameter Extraction: Extract values from element text or attributes (URL parameters in Pro)
- Debug Mode: Comprehensive logging for troubleshooting
- Modern Architecture: PHP 8.1, PSR-4 autoloading, WordPress coding standards compliant
- Performance Optimized: Efficient JavaScript injection and event handling
- Extensible: Gating provider + hook API for add-ons (EventLayer Pro)
Pro features (via the EventLayer Pro add-on): site location targeting, trigger delays, stop propagation, child selectors, per-instance element control, URL parameter extraction, scheduling, import/export, and unlimited rules (free is capped at 5). See PRO-GATING.md for the full split.
- WordPress 6.4 or higher
- PHP 8.1 or higher
- Modern browser with JavaScript enabled
- Download the plugin zip file
- Go to Plugins β Add New in your WordPress admin
- Click Upload Plugin and select the zip file
- Click Install Now and then Activate Plugin
- Upload the
eventlayerfolder to/wp-content/plugins/ - Activate the plugin through the Plugins menu in WordPress
composer require spotfin/eventlayer- Navigate to EventLayer in your WordPress admin menu
- Click "Add New" to create your first event rule
- Configure your event:
- Event Type: GA4 event name (e.g.,
button_click) - Parent Selector: CSS selector for trigger element (e.g.,
.cta-button) - Parameters: Data to send with the event
- Event Type: GA4 event name (e.g.,
- Publish the event rule to activate it
- Test by enabling debug mode in EventLayer β Settings
Event Type: button_click
Parent Selector: .download-button
Parameters:
- button_text: Element Text β (uses clicked element's text)
- section: Static Value β "hero"
Event Type: form_submit
Parent Selector: form.contact-form
Parameters:
- form_name: Element Attribute β data-form-name
- page_section: URL Parameter β section
Event Type: link_click
Parent Selector: a[href*="external"]
Site Location: All Pages (Pro)
Trigger Delay: 100ms (Pro)
Stop Propagation: Yes (Pro)
Parameters:
- link_url: Element Attribute β href
- link_text: Element Text
- click_source: Static Value β "navigation"
For a button like this:
<a class="test-button" href="https://google.com" target="_blank">Button Text</a>EventLayer Configuration:
- Event Type:
link_click - Parent Selector:
a.test-button - Site Location: All Pages (Pro)
- Trigger Delay: 100ms (Pro)
- Stop Propagation: Yes (Pro)
Parameters:
| Parameter Name | Target Type | Target Selector | Default Value |
|---|---|---|---|
button_text |
Element Text | (clicked element) | - |
button_url |
Element Attribute | href |
- |
button_target |
Element Attribute | target |
- |
button_class |
Static Value | - | test-button |
Result in dataLayer:
{
event: 'link_click',
button_text: 'Change This',
button_url: 'https://google.com',
button_target: '_blank',
button_class: 'test-button'
}Track all external links:
Parent Selector: a[href^="http"]:not([href*="yourdomain.com"])
Track specific URL:
Parent Selector: a[href="https://google.com"]
Track by multiple attributes:
Parent Selector: a.test-button[target="_blank"]
- Event Type: The GA4 event name sent to dataLayer
- Site Location (Pro): Where the event should be active
- Trigger Delay (Pro): Delay before event fires (in milliseconds)
- Stop Propagation (Pro): Prevent event bubbling
- Schedule (Pro): Only fire between a start and end datetime
- Parent Selector: CSS selector for the trigger element; events fire on all matching elements
- Multiple Elements (Pro): Per-instance control over matched elements
- Child Selectors (Pro): Additional selectors for more specific targeting
Each parameter can extract values using different target types:
- Static Value: Uses the default value
- Element Text: Extracts text content from target element
- Element Attribute: Extracts attribute value (e.g.
href,data-*) - URL Parameter (Pro): Extracts value from query string
Access plugin settings via EventLayer β Settings:
- Debug Mode: Enable console logging for troubleshooting
- Auto Page View Tracking: Automatically track page views
- PHP 8.1+
- Composer (assets are plain CSS/JS; no Node or build step required)
# Clone the repository
git clone https://github.com/Spotfin/EventLayer.git
cd EventLayer
# Install PHP dependencies
composer install
# Install and configure coding standards
composer run phpcs:setupThe project follows WordPress coding standards. Use these commands for code quality:
# Check all files
composer run phpcs
# Fix all auto-fixable issues
composer run phpcbf
# Check just the src/ directory
composer run phpcs:src
# Fix just the src/ directory
composer run phpcbf:src
# Get a summary report
composer run lintcomposer run phpcs # Run PHP CodeSniffer
composer run phpcbf # Run PHP Code Beautifier and Fixer
composer run phpcs:src # Check src/ directory only
composer run phpcbf:src # Fix src/ directory only
composer run phpcs:main # Check main plugin file only
composer run phpcbf:main # Fix main plugin file only
composer run lint # Quick summary report
composer run fix # Fix all issueseventlayer/
βββ eventlayer.php # Main plugin file
βββ composer.json # Composer configuration
βββ phpcs.xml # PHP CodeSniffer rules
βββ README.md # This file
βββ readme.txt # WordPress plugin readme
βββ src/ # Source code
β βββ Plugin.php # Main plugin class
β βββ Admin/ # CPT, meta boxes, menu, settings, gating UI
β β βββ Views/ # Admin templates
β βββ Data/ # EventRuleRepository (all meta/query access)
β βββ Frontend/ # Script injection
β βββ Gating/ # GatingProvider seam (free/pro)
β βββ Model/ # EventRule, Parameter, enums
β βββ Assets/ # CSS and JavaScript
β βββ Tests/ # Test files
βββ languages/ # Translation files
βββ vendor/ # Composer dependencies
EventLayer uses a modern architecture with:
- PSR-4 Autoloading: Organized namespace structure
- Custom Post Types: Native WordPress data storage
- Meta Boxes: Rich admin interface
- Hook-based System: Extensible via WordPress actions/filters
- Singleton Pattern: Single plugin instance
- Repository Pattern: Clean data access layer
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run code quality checks (
composer run lint) - Fix any issues (
composer run fix) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow WordPress Coding Standards
- Use PHP 8.1+ features appropriately (typed properties, promoted constructors, enums, readonly)
- Maintain backwards compatibility
- Add inline documentation for all public methods
- Write unit tests for new functionality
Enable debug mode in EventLayer β Settings to see console output:
- Event initialization messages
- Trigger confirmations
- Parameter extraction details
- Error messages
Events not firing:
- Check CSS selectors are correct
- Verify elements exist on the page
- Ensure event rule is published
- Check browser console for errors
Parameters not working:
- Verify target selectors
- Check parameter target types
- Test with static values first
JavaScript errors:
- Enable debug mode
- Check browser console
- Verify jQuery is loaded
This is the extension API used by EventLayer Pro; third-party plugins can use it too.
// Replace the gating provider (must implement EventLayer\Gating\GatingProvider).
$provider = apply_filters( 'eventlayer_gating_provider', $default_free_provider );
// Add or modify parameter target types.
$target_types = apply_filters(
'eventlayer_parameter_target_types',
array(
'static' => __( 'Static Value', 'eventlayer' ),
'element_text' => __( 'Element Text', 'eventlayer' ),
'element_attribute' => __( 'Element Attribute', 'eventlayer' ),
)
);
// Whether a rule is injected on the current request.
$active = apply_filters( 'eventlayer_rule_is_active', $active, $rule );
// The settings object pushed to JS (eventLayerSettings).
$settings = apply_filters( 'eventlayer_frontend_settings', $settings );
// The full rule config pushed to JS (eventLayerConfig).
$rules = apply_filters( 'eventlayer_frontend_config', $rules );// Add rows to the Event Settings meta box.
do_action( 'eventlayer_event_settings_fields', $rule, $post );
// Add rows to the Trigger Elements meta box.
do_action( 'eventlayer_trigger_elements_fields', $rule, $post );Note: debug mode is controlled by the eventlayer_debug_mode option (Settings β Debug Mode), not a filter.
This project is licensed under the GPL-2.0+ License - see the LICENSE file for details.
EventLayer is developed by Spotfin Creative, a WordPress development agency specializing in custom solutions and performance optimization.
Made with β€οΈ by Spotfin Creative


