inPIPE by Seresa

Plugin Banner

inPIPE by Seresa

by Seresa

Download
Description

inPIPE by Seresa allows you to generate, store, and manage UTM parameters—both plain and coded. The plugin automatically decodes coded UTM query strings when visitors land on your website, pushing the full UTM data to the dataLayer. This helps bypass ad blockers and improves tracking in Google Analytics, Facebook Ads, and other platforms.

  • Generate & manage UTM query strings with ease
  • Supports both plain and coded UTM parameters
  • Decodes coded UTM links on-site and sends data to the dataLayer
  • Reduces tracking disruptions caused by ad blockers
  • Works with GA4, GTM, Facebook Ads & more
  • NEW — UTM API Access: connect external tools, scripts, and AI automations to your saved UTM links through a secure, key-protected REST API

Use WP inPIPE for more reliable UTM tracking and better data collection!

Features

  • Generate and store UTM query string URLs based on user input
  • Encode UTM parameters to enhance tracking accuracy
  • Decode UTM query strings on site visits and push the original UTM data to the dataLayer
  • Potentially bypass ad blockers to ensure accurate data collection

UTM API Access — External REST API (new)

Connect external tools, scripts, and AI automations directly to your UTM links through a secure, key-protected REST API. Enable it from the UTM API Access panel (shown when UTM Processing is on), provision your scoped keys, and call four server-to-server endpoints under /wp-json/inpipe/v1/ext/:

  • POST /inpipe/v1/ext/utm-generate — create a new UTM-tagged link, or update an existing one by its short code
  • GET /inpipe/v1/ext/utm-list — retrieve your saved UTM records, with filtering and pagination
  • DELETE /inpipe/v1/ext/utm-delete — permanently delete a record by its short code
  • GET /inpipe/v1/ext/status — check the API toggle states and your current rate-limit budgets

Secured with HTTPS-only transport, two scoped API keys (read-only and read-write, encrypted at rest), per-operation rate limiting, per-site IP throttling, a same-site domain guard, and an admin-configurable storage cap.

Example — create a UTM-tagged link (POST /inpipe/v1/ext/utm-generate):

curl -X POST https://your-site.com/wp-json/inpipe/v1/ext/utm-generate \
  -H "X-InPipe-Key: YOUR_READ_WRITE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "base_url": "https://your-site.com/landing",
    "utm_source": "newsletter",
    "utm_medium": "email",
    "utm_campaign": "summer_sale",
    "custom_params": [ { "key": "partner", "value": "acme" } ]
  }'

Example response:

{
  "success": true,
  "error": null,
  "data": {
    "code": "u4gf2",
    "coded_url": "https://your-site.com/landing?u4gf2=84729301",
    "full_url": "https://your-site.com/landing?utm_source=newsletter&utm_medium=email&utm_campaign=summer_sale",
    "utm_source": "newsletter",
    "utm_medium": "email",
    "utm_campaign": "summer_sale",
    "custom_params": [ { "key": "partner", "value": "acme" } ],
    "created_at": "2026-06-19T10:24:00Z",
    "updated_at": "2026-06-19T10:24:00Z"
  }
}

Full documentation, authentication details, and more code examples: inPIPE UTM API Documentation

Configuration

  • Navigate to Admin Dashboard > inPIPE to manage plugin settings.
  • Enable automatic UTM processing in the settings panel.
  • Use the UTM Coder to create, edit, or delete UTM query strings.

External Services

This plugin connects to external services hosted by Seresa.io for the following purposes:

Subscription Verification & Premium Package Downloads
Service: The plugin uses the API at [https://sub.seresa.app] to verify premium subscriptions and to download premium packages or updates.
When:
– Subscription verification occurs when you attempt to access premium features or validate your license.
– Package downloads occur when you install or update premium components from within the plugin.
Data Sent:
– The plugin sends your license key, site URL, and (if applicable) the requested package identifier to the API.
Purpose:
– To verify your entitlement to premium features and to deliver premium package files securely.
Terms of Service: [https://seresa.io/terms]
Privacy Policy: [https://seresa.io/privacy]

Other Hosted Services
– See below for additional premium features that may rely on external event processing (e.g., Transmute Engine).

  1. Subscription Verification

    • What: The plugin connects to https://sub.seresa.app/premium-downloader/v1/verify-subscription to validate subscription codes
    • When: This occurs only when a user enters a subscription code in the admin panel to activate premium features
    • Data sent: Subscription code entered by the user, site URL, and WordPress version
    • Purpose: To verify the validity of subscription purchases and enable premium features
    • Provider: Seresa.io – Terms of Service and Privacy Policy
  2. Package Installation

    • What: The plugin connects to https://sub.seresa.app/premium-downloader/v1/download to download premium components
    • When: This occurs only after subscription verification when the user initiates the installation of premium features
    • Data sent: Verified subscription code, site URL, WordPress version, and PHP version
    • Purpose: To securely download and install authorized premium components
    • Provider: Seresa.io – Terms of Service and Privacy Policy
  3. Transmute Engine (Premium Feature)

    • What: Premium users’ event data is processed through Transmute Engine, a server-side event processing service
    • When: When events are triggered on your website (page views, clicks, form submissions, etc.)
    • Data sent: Event data, UTM parameters, and tracking information
    • Purpose: To process and route event data to your configured third-party services
    • How it works: Transmute Engine acts as a first-party server to your website, temporarily processing data without permanent storage, and forwarding it to your specified endpoints
    • Provider: Seresa.io – Terms of Service and Privacy Policy

No data is shared with third parties beyond Seresa.io, and all connections use secure HTTPS encryption. Users can choose not to use premium features, in which case no external connections will be made.

Third-Party Libraries

This plugin uses the following third-party libraries:

  1. Vue.js

    • What: A progressive JavaScript framework for building user interfaces
    • Website: https://vuejs.org/
    • License: MIT License – https://github.com/vuejs/vue/blob/main/LICENSE
  2. Vue Toastification

    • What: Toast notification library for Vue.js
    • Website: https://github.com/Maronato/vue-toastification
    • License: MIT License
  3. Lucide Icons

    • What: Beautiful & consistent icon toolkit for Vue.js
    • Website: https://lucide.dev/
    • License: ISC License – https://github.com/lucide-icons/lucide/blob/main/LICENSE
  4. Axios

    • What: Promise-based HTTP client for JavaScript
    • Website: https://axios-http.com/
    • License: MIT License
  5. Pinia

    • What: State management library for Vue.js
    • Website: https://pinia.vuejs.org/
    • License: MIT License
  6. Vue I18n

    • What: Internationalization plugin for Vue.js
    • Website: https://vue-i18n.intlify.dev/
    • License: MIT License
  7. Tailwind CSS

    • What: Utility-first CSS framework
    • Website: https://tailwindcss.com/
    • License: MIT License
  8. WordPress JavaScript Libraries

    • What: Official WordPress JavaScript libraries (@wordpress/api-fetch, @wordpress/components, @wordpress/element, @wordpress/i18n)
    • Website: https://developer.wordpress.org/block-editor/reference-guides/packages/
    • License: GPL-2.0+ License

All third-party libraries used are compatible with the GPL-2.0+ license of this plugin.

Build Tools and Source Code Access

This plugin uses modern frontend tools (Vue.js, Vite, Axios) to build its admin interface. The full, human-readable source code is included directly within the plugin package under the /src directory.

Included source code:
• /src/ contains all original Vue 3 components, Pinia store, and JavaScript modules
• /dist/ contains the compiled production build
• /src/README.md contains full build instructions and configuration references

Build Toolchain:
• Vue.js 3
• Vite
• Tailwind CSS
• PostCSS
• Vitest
• Grunt

To rebuild the admin interface from source:
1. Navigate to the /src directory
2. Run npm install
3. Run npm run build:free or npm run build:premium to compile assets to /dist

This ensures full compliance with WordPress.org’s guidelines requiring human-readable source code for all minified or bundled assets.

For detailed developer instructions, see /src/README.md.

License

This plugin is licensed under the GNU General Public License v2.0 or later.
For more details, visit: https://www.gnu.org/licenses/gpl-2.0.html

Support

For free users: Report issues on our GitHub page:
🔗 GitHub Issues

For general inquiries, contact us at support@seresa.io.

For premium users: Get priority support at 🔗 seresa.io/support.

  1. Upload the plugin folder to your WordPress plugin directory (wp-content/plugins/).
  2. Activate the plugin through the Plugins > Installed Plugins menu in WordPress.
Can I use this plugin just to generate UTM parameter query strings?

Yes! The plugin allows you to easily generate UTM parameter query strings for your marketing campaigns. You can create both plain and coded UTM query strings with simple click options. If you only need to generate and use UTM parameters without decoding, you can do so without enabling the decoding feature.

Can I use plain UTM parameters instead of coded ones?

Yes! The plugin supports both plain and coded UTM parameters. If you don’t enable decoding, your standard UTM parameters will work as usual. If you want extra protection against ad blockers, you can enable decoding in the plugin settings.

How do I enable coded UTM decoding?

Go to Settings > WP inPIPE and turn on the option for Coded UTM Processing. When enabled, the plugin will detect and decode coded UTM query strings, replacing them with the full UTM parameters in the URL bar and pushing them to the dataLayer.

How does this help with Google Tag Manager (GTM)?

By pushing decoded UTM parameters directly into the dataLayer, Web GTM can receive the data without requiring extra configurations to extract and manage UTM values. This simplifies tracking setup and ensures cleaner data in your analytics.

What is UTM API Access?

UTM API Access is a secure, key-protected REST API that lets external tools, scripts, and AI automations create, list, update, and delete your UTM links without using the dashboard. It exposes four server-to-server endpoints under /wp-json/inpipe/v1/ext/utm-generate, utm-list, utm-delete, and status. Full details, authentication, and code examples are in the inPIPE UTM API Documentation.

How do I enable the UTM API and get my API keys?

First make sure UTM Processing is enabled, then open the UTM API Access panel in the inPIPE settings. Turn on the master toggle to provision your two scoped keys — a read-only key (for utm-list and status) and a read-write key (also required for utm-generate and utm-delete). You can copy or regenerate the keys at any time from the panel.

Is the UTM API secure?

Yes. Every request is served over HTTPS only and must carry a valid API key. The two keys are scoped (read-only vs. read-write) and stored encrypted at rest using libsodium, with the encryption key derived from your wp-config salts and never written to the database. The layer also applies per-operation rate limiting, per-site IP throttling, a same-site domain guard, and a storage cap. The endpoints are server-to-server only (browser CORS is suppressed).

Where can I find full UTM API documentation?

Complete documentation — endpoint reference, request/response formats, authentication, rate limits, and examples — is available here: inPIPE UTM API Documentation

Premium version

By ender015 on July 7, 2025

Hi, I just downloaded your plugin — it’s really helpful for suppressing adblockers. I was wondering if you have plans to release a premium version soon? Looking forward to it!

2.0.1 – 2026-07-15

Bug fixes: stale dropdown values and reappearing custom parameters when editing a stored UTM URL

BUG FIXES

  • UTM Coder — Edit no longer offers deleted dropdown values: Opening a stored UTM URL for editing now refreshes the parameter dropdown options from the server first, so a value that was deleted in another browser tab or an earlier session is never offered again
    • Previously the dropdown options were loaded only once when the page opened, so a second open browser could keep showing an option that had already been removed
    • The edit form now re-fetches the current options before populating, keeping the dropdowns in sync with the saved list
    • No change to validation, sanitization, or what gets saved — only which options are shown
  • UTM Coder — Removed custom parameters no longer reappear on the next edit: Editing a stored UTM URL, removing a custom parameter, and saving now clears it for good
    • Previously the parameter was correctly dropped from the saved URL, but re-opening the record for editing brought it back into the input fields
    • The removed parameter was left behind in the database and rebuilt when the record was re-opened; saving now clears the vacated custom-parameter slots so the input fields always match the saved URL

TECHNICAL

  • handleEdit() in inPipeUTMCoderComponent.vue now awaits fetchUtmOptions() before populating the form
  • Added nocache_headers() to the inpipe-utm-options-fetch REST handler — the GET endpoint previously sent no cache directives, so on servers without a FastCGI/CDN bypass rule the options list could be served stale
  • save_utm_url() in class-inpipe-utm-decoder.php now blanks unused utm_customN_* column pairs on update — $wpdb->update() only touched the columns it was handed, so a reduced/removed custom param previously left stale pairs that the fetch endpoint rebuilt into the edit form
  • Removed the now-redundant external-API workaround for this (set_custom_params() in class-inpipe-external-record-store.php and its call in the write adapter) — the fix at the save layer covers every write path
  • Added unit coverage for refetch-on-edit and fetch-before-populate ordering (tests/unit/UTMCoderComponent.test.ts)

DOCS

  • Rewrote the plugin short description to lead with agentic/REST API UTM tracking (“Agentic-ready UTM tracking via REST API. Mask, store, and decode UTM parameters for Google Analytics, Facebook Ads, and more.”)

2.0.0 – 2026-06-24

UTM API Access, Stored UTM Attribution, Premium Update Reminder, In-Place Updates, Plugin List Enhancements, UTM Decoding Reliability & Performance

NEW FEATURES

  • Stored UTM URLs — Creator & Editor Attribution: Each stored UTM URL now records and displays who created it and who last edited it, alongside the existing “Created” date
    • URLs saved from the dashboard are attributed to the logged-in WordPress user (shown by display name)
    • URLs created or updated through the External UTM API are attributed to “API”
    • The “Last Edited” date and editor only appear once a record has actually been changed (unedited records show just “Created”)
    • Records created before this release show no attribution (graceful fallback — no raw values shown)
    • External UTM API list/read responses include privacy-safe created_by / updated_by fields — collapsed to "user" or "API" so internal WordPress user IDs are never exposed to third-party integrations
    • New created_by / updated_by columns on the inpipe_utm_codes table; existing sites migrate automatically on upgrade with no data loss
  • UTM API Access — External REST API: Securely connect external tools and automations to your UTM links with a key-protected REST API (new “UTM API Access” panel, shown when UTM Processing is enabled)
    • Four server-to-server routes under /wp-json/inpipe/v1/ext/: utm-generate (create/update), utm-list, utm-delete, and status
    • Two scoped API keys — read-only and read-write — provisioned per site and regenerable from the dashboard
    • Keys are stored encrypted at rest via libsodium (InPipe_Encryption), with the encryption key derived from the wp-config auth salts (never written to the database); only a masked display string is shown after first reveal
    • Per-operation, three-tier rate limiting — per-second / per-minute / per-hour windows (read 10/300/10000, write 10/300/5000, delete 5/30/1000), fixed shared-hosting-safe ceilings (not admin-editable) — plus a site-wide request ceiling and per-site salted-IP throttling with escalating bans; over-limit responses carry a Retry-After header
    • Domain guard fails closed — base_url must resolve to this site’s own host before a write is accepted
    • Admin-configurable storage cap gates new creates (HTTP 507); existing inventory stays fully readable (grandfathered)
    • CORS is suppressed on the namespace (server-to-server only — no browser caller), and the layer ships its own request logger for diagnostics
    • Documentation links surfaced throughout the UI: the Settings “Enable UTM Processing with API” label links to the API docs, and the UTM Coder shows an “API” button (linking to the docs) whenever UTM API Access is disabled, hidden once it is enabled
  • UTM Coder — Rename & Smarter Validation: Saved dropdown options can now be renamed in place, and per-field validation is more permissive where it should be
    • New “rename option” action on UTM parameter dropdowns
    • content and term fields now accept spaces; apostrophes are normalized rather than rejected
    • Other fields still reject spaces and invalid characters with a clear toast message
  • Visitor IP REST Endpoint: New public /wp-json/inpipe/v1/visitor-ip endpoint resolves the visitor IP from server headers (Cloudflare / X-Forwarded-For / X-Real-IP / REMOTE_ADDR)
    • Fallback for cached pages where inPipeConfig.visitorIp from wp_localize_script is stale
    • Honors the inpipe_anonymize_ip setting via wp_privacy_anonymize_ip()
  • Premium Update Reminder: Display-only “update available” notice for the premium plugin via the Seresa API

    • Polls the Seresa update-check API on a throttled, jittered schedule from the admin screens (avoids thundering herd; each site checks at its own consistent offset)
    • Shows an “Update now” reminder row under the plugin on the Plugins page, linking to the inPIPE settings page where the premium installer applies the update
    • Display-only by design — does not modify WordPress’s plugin-update system, keeping the free plugin fully WordPress.org-compliant and unable to interfere with its own .org-delivered updates
    • Manual force-check available from the Vue dashboard
    • Cache cleared automatically when subscription changes
  • In-Place Premium Updates: Premium users can now update without re-downloading the full package

    • New update parameter on premium install API endpoint allows re-installation when already active
    • Requests unified-premium package type for updates vs plugin for first-time upgrades
    • Routes update through InPipe_Premium_Updater (premium class) for full plugin replacement
    • Falls back to standard integrator for first-time upgrade flow
  • Plugin List Enhancements: Richer plugin row in WordPress Plugins page

    • “Update Available” action link (red, bold) when premium update detected — links to settings
    • “Docs & Support” meta link pointing to support.seresa.io
    • “API” meta link (between “Docs & Support” and “Go Premium”) pointing to the UTM API documentation
    • “Go Premium” meta link (red, bold) for free users pointing to seresa.io/pricing
    • Plugin name, description, and version dynamically change when premium is active
  • Gorilla Food Cookie — Rolling Renewal: The gorilla_food visitor cookie now uses a sliding 400-day expiry instead of a fixed expiry from first visit

    • Returning visitors have their cookie refreshed on every page load via the /wp-json/inpipe/v1/gorilla-food REST endpoint
    • Identity persists indefinitely as long as the visitor returns within the browser’s cookie ceiling (RFC 6265bis)
    • Renewal runs in a REST context only — Set-Cookie headers cannot be captured by page caches (WP Super Cache, W3TC, LiteSpeed, Cloudflare)
    • Cookie value is never rotated — only the expiry slides forward, preserving attribution continuity
    • Malformed incoming cookies are rejected before re-emission, blocking session-fixation attempts
  • Gorilla Food — Public Hooks for Consumer Plugins: New WordPress hooks expose the visitor UID to other inPIPE™ ecosystem plugins

    • inpipe_get_gorilla_food() — function returning the current visitor UID (or null)
    • inpipe_gorilla_food — filter for overriding/extending the UID before it reaches consumers
    • inpipe_user_identified — action fired on init (priority 5) when a UID is present, primary integration point for consumer plugins
    • Consumer plugins should use these hooks rather than reading the cookie directly

IMPROVEMENTS

  • Stored UTM URLs — Search & Pagination: The saved-UTM list in the dashboard now has a search box (filter by URL/params) and paginated results, so large inventories stay manageable
  • UTM Decode Caching: Decoded UTM keys are cached in a 6-hour transient — repeat requests for the same key return instantly and bypass rate limiting entirely (same key always decodes to the same params)
  • Higher UTM Rate Limit: Uncached UTM decode requests raised from 50 to 200 per hour per IP
  • Reliable UTM Handoff Across Navigation: Original coded URL data and decoded events are written to sessionStorage synchronously before navigation, so the destination page can emit utm_decoded / inPIPE_utm_decoded reliably (previously beforeunload fetches were cancelled by the browser on hard navigations)
  • UTM Decoder Retry: The decode request now retries once (after 300ms) on transient 502/503/504 responses caused by PHP-FPM overload or brief restarts
  • Faster DB Version Check: inpipe_maybe_upgrade_db() bails early when inpipe_db_version already matches, avoiding a DB query on every request
  • Subscription Data Enrichment: Upgrade process now saves additional fields from the verification API response
    • subscription_creation extracted from current_subscription_start (fixes “Activated On: Unknown” in subscription panel)
    • subscription_name extracted from plan_brand_name (e.g., “Cerise”)
    • events_allowance seeded into usage data immediately on upgrade (no longer waits for first webhook)
  • Subscription Plan Validation: Updated valid plans — added harvest and entry, removed business
  • Premium Version Source: inpipe_get_premium_version() now prefers INPIPE_PREMIUM_VERSION constant (set at load time) over database option for accuracy
  • Frontend Premium Version: premiumVersion now exposed to Vue admin settings for dashboard display
  • Package Installer Return Values: Fixed three code paths that returned void instead of WP_Error — callers can now properly detect and handle failures
  • Premium Version Sync: After install/upgrade, calls the update-check API to set the correct inpipe_premium_version in the database — fixes version staying at default 1.0.0 or 2.0.0
  • Subscription Vue Data Enrichment: get_subscription_data() now exposes additional fields to the Vue admin dashboard
    • planBrandName and billingPeriod merged from inpipe_subscription option (set by Seresa webhook)
    • outpipesLimit, outpipesAddonCount, outpipesAddonLimit, outpipesAddonAvailable from inpipe_outpipe_data option
    • outpipesActive — live count of active outPIPEs via InPipe_Premium_Connections_Manager (premium only)

BUG FIXES

  • Rate Limit on Premium Upgrade: Subscription verification now correctly handles HTTP 429 responses with a clear “too many attempts” message instead of falling through to a generic error
    • Simplified the Vue-side 429 detection (removed brittle string matching on the error message)
  • UTM Coder — Landing page path is now editable after it’s locked: Clicking the Landing Page field once UTM parameters have been added (or after the path was confirmed) now re-opens it for editing instead of showing a “Reset All to edit” notice
    • Previously the path could only be changed by clearing the entire form, because the field was replaced by the live UTM query preview / a read-only value once any parameter existed
    • Editing runs the same five-layer path validation as the original confirm step, then re-locks the field — no security or sanitization change
    • The confirm (✓) button and Enter/blur all confirm an inline edit; the regenerated full and coded URLs update automatically, and the coded URL keeps its original id so shared links don’t break

NEW FILES

  • includes/core/api/external/ — UTM API Access layer (24 files): external endpoints (class-inpipe-api-endpoints-external.php), admin controller, settings, request logger, plus adapter/, storage/, ratelimit/, handlers/, validation/, and flow/ subsystems
  • includes/core/class-inpipe-encryption.php — libsodium encryption util promoted to core (from premium) for API-key storage at rest
  • src/shared/ExternalApiPanel.vue — “UTM API Access” settings panel
  • includes/free/premium-upgrade/class-inpipe-premium-update-checker.php — Premium update checker with jitter-based caching

TECHNICAL

  • Registered the four /inpipe/v1/ext/* external routes plus admin routes (/inpipe-ext-settings, /inpipe-ext-regenerate-key) gated by manage_options + nonce
  • Added generate_unique_code() public wrapper on InPipe_UTM_Decoder so the external write adapter can mint collision-checked short codes without a browser
  • Added inpipe_setting_updated-driven external config refresh and ExternalApiPanel.vue injection via the new settings after-header slot
  • External UTM API endpoints exposed in src/utils/inPipeApiEndpoints.js
  • Added handle_visitor_ip() and registered the /visitor-ip route in InPipe_API_Endpoints_Free
  • Added transient caching (inpipe_utm_decoded_{key}) in the UTM decode handler and a cache short-circuit in validate_public_utm_request()
  • Added case 429 handling to InPipe_Subscription_Manager verification response mapping
  • Added inpipe_setting_updated action hook (fired after a setting is saved) in InPipe_Settings_Manager
  • Added an after-header slot to inPipeSettingsComponent.vue for premium content injection
  • Added fetchWithRetry() and synchronous sessionStorage writes in inPipeUtmDecoder.js
  • Added handleRenameOption() and per-field space/apostrophe handling in inPipeUTMCoderComponent.vue
  • Added isEditingPath state and confirmPathEdit() to inPipeUTMCoderComponent.vue so a locked landing-page path can be re-opened for editing (click-to-unlock); .landing-path-input cursor reflects clickable/editable states
  • Added $is_update property and parameter to InPipe_Package_Installer::install_premium_package()
  • Added update parameter handling in handle_premium_install() API endpoint
  • Added add_row_meta() and modify_plugin_description() methods to InPipe_Plugin
  • Registered InPipe_Premium_Update_Checker in plugin bootstrap (only when premium is active)
  • Added InPipe_Premium_Update_Checker::cleanup() to uninstall routine
  • Fixed install_premium_package() to return true on success, WP_Error on failure (was void)
  • Added sync_premium_version() to InPipe_Package_Installer — queries update-check API post-install to set correct premium version
  • Added InPipe_Gorilla_Food_Manager::renew_cookie() — re-emits existing cookie with fresh expiry; validates input, no-ops for bots / sent headers / missing or invalid cookie
  • Added InPipe_Gorilla_Food_Integration::renew_cookie() static facade — lazily instantiates manager when called from REST context
  • Added InPipe_Gorilla_Food_Integration::broadcast_user_identified() — fires inpipe_user_identified action on init priority 5 when a UID is present
  • Added inpipe_get_gorilla_food() function with inpipe_gorilla_food filter in inpipe-gorilla-food-functions.php
  • Updated handle_gorilla_food() REST handler to call renew_cookie() for returning visitors (rolling renewal)
  • Replaced misleading httponly inline comment in InPipe_Gorilla_Food_Manager::set_cookie() — JS reads value via REST endpoint, not the cookie

1.1.1 – 2026-02-12

UTM Import, Dropdown Options Management, Edit UX Overhaul, Validation & Security Enhancements

NEW FEATURES

  • Quick Import UTM: Paste any URL containing UTM parameters and auto-fill the form

    • Supports full URLs, query-only strings, bare parameters, and URLs without protocol
    • Six-step validation chain: empty check, 512-char length cap, multiple URL detection, dangerous protocol blocking, URL parsing with fallbacks, and UTM parameter extraction
    • Extracts standard UTM parameters (source, medium, campaign, term, content, id)
    • Now also picks up all non-standard query parameters as custom parameters (up to 3), not just utm_* prefixed ones
    • Domain validation: rejects URLs that don’t match the site domain
    • Warning toast when custom parameters exceed the limit, showing how many were skipped
    • Landing path extracted from URL and auto-confirmed
    • Import UTM button in card header next to Reset All
  • UTM Dropdown Options Management: Custom dropdown values for all six UTM parameter fields

    • New inpipe_utm_options database table with seeded defaults and user-added values
    • Add custom values inline via dropdown input (auto-saved to server immediately)
    • Delete any option (including defaults) via delete icon in dropdown
    • Options loaded from server on mount via InPipe_UTM_Options_Manager with 24-hour object caching
    • Toast feedback on add (“{value} added”) and delete (“{value} removed”)
  • Landing Page Path Confirmation: Confirm-before-edit workflow for the landing page path

    • Three-state field: editable input with checkmark confirmed display live query preview
    • Five-layer path validation: query characters (?#&=), UTM parameter patterns, character allowlist, path traversal/dot abuse, consecutive slashes
    • UTM params lock overlay when path is typed but not confirmed (prevents editing UTM fields until path is confirmed)
    • Users can skip the path entirely and go straight to UTM params
  • Live UTM Query Preview: Real-time preview of the URL being built inside the landing page field

    • Shows page/subpage?utm_source=google&utm_medium=cpc&custom_key=value as params are selected
    • Replaces the editable input once any UTM parameter has a value

UTM EDIT UX OVERHAUL

  • Editing State Indicator: Blue banner below card header when editing a stored UTM
    • Shows pencil icon, “Editing UTM:” label, and the UTM ID in a monospace badge
    • Cancel button to exit edit mode and clear the form
  • Save Button Context: Button changes from “Save UTM” to “Update UTM” with pencil icon when editing
  • Active UTM Highlight: Stored UTM item being edited gets a blue border and tint
  • Saved UTM Highlight: Newly saved or updated UTM gets a primary-color highlight with 3-second fade-out animation, auto-scrolls into view
  • Auto-Copy on Save: Coded URL is automatically copied to clipboard after saving
    • Toast message: “UTM saved — coded URL copied to clipboard!”
    • Graceful fallback if clipboard access is denied
  • Param Value Indicators: UTM parameter cards show primary-color border when they have a value
  • Scroll Behavior: Edit and import scroll to the top of the UTM Parameters card; save scrolls to the highlighted stored UTM

EDIT BUG FIXES

  • Fixed hasUnsavedChanges: Now compares against a snapshot of the loaded UTM values instead of static empty defaults
  • Fixed Coded URL Regeneration: Editing a UTM no longer generates a new random coded URL value on every keystroke — preserves the original coded URL so shared links aren’t broken
  • Fixed Watcher During Edit Load: Added isLoadingEdit guard to prevent the deep watcher from firing multiple times while populating the form during edit
  • Fixed Custom Params Shallow Copy: Edit now deep-copies custom parameters to prevent mutation of stored UTM data

SECURITY ENHANCEMENTS

  • Allowlist-Based Sanitization: Replaced blocklist sanitizeUtmValue() with normalize-and-allowlist approach

    • NFKC normalization collapses fullwidth characters (e.g., google google)
    • Strips zero-width characters, directional overrides, and BOM marks
    • Allowlist filter: only a-z, 0-9, _, -, ., space survive
    • Blocks emoji, non-standard whitespace, control characters, and all non-Latin input
  • Strict Custom Key Sanitization: New sanitizeCustomKey() function for custom parameter keys

    • Only a-z, 0-9, _, - allowed (no spaces or periods)
  • Custom Parameter Input Validation: Blur-based validation for custom parameter keys and values

    • Key validation: rejects invalid characters, standard UTM name collisions, utm_ prefix, and duplicate keys
    • Value validation: rejects query-breaking and injection characters
    • Immediate feedback via warning toasts — invalid input is rejected and field is cleared on blur
    • Uppercase input silently normalized to lowercase on blur (e.g., TEST test)
    • Save-time sanitization via sanitizeCustomKey() / sanitizeUtmValue() as final safety net
  • Dropdown Value Sanitization: handleAddFromDropdown() sanitizes via allowlist before setting v-model

    • Strict equality check rejects any input altered by sanitization (e.g., <script>alert(1)</script> rejected)
    • Dirty value guard in watcher silently clears pre-existing dirty options on selection
  • Landing Page Path Hardening: Five-layer validation for the landing page path

    • Layer 3: Character allowlist — only a-z, 0-9, -, _, ., / allowed (rejects commas, spaces, special chars)
    • Layer 4: Path traversal protection — blocks ../, ./, leading/trailing dots, /. patterns
    • Layer 5: Malformed path detection — blocks consecutive slashes (//)
  • Import Domain Validation: Imported URLs are validated against the site domain — mismatched domains are rejected with a clear error message

IMPROVEMENTS

  • inPipeBaseSelect Component: Complete rebuild with custom dropdown mode

    • Custom dropdown with deletable options, inline custom value input, keyboard navigation
    • ARIA combobox/listbox roles for accessibility
    • Click-outside close, escape key handling, arrow key navigation with highlighted index
    • Falls back to native <select> when deletableOptions is not provided
  • Coded URL Landing Path: Both full URL and coded URL now include the landing page path

  • Placeholder Update: Landing page placeholder changed to page/subpage
  • Emoji to Lucide Icons: Replaced all emoji icons in UTM Coder with Lucide icon components (Download, RefreshCcw, Pencil, Trash2, Save, Copy, Check, Loader, Plus, Zap, CircleAlert, Rocket)
  • Stored UTMs Spacing Fix: Fixed space-y (Tailwind-only utility) not working in plain CSS — replaced with flexbox gap for proper spacing between stored UTM items and URL rows

NEW FILES

  • includes/core/class-inpipe-utm-options-manager.php — UTM dropdown options CRUD with WordPress object caching

TECHNICAL

  • Bumped INPIPE_DB_VERSION from 1.0.0 to 1.1.0 to trigger database upgrade for users updating from v1.1.0 — ensures inpipe_utm_options table is created via dbDelta
  • Added inpipe_utm_options table: id, field_name, option_value, is_default, created_at, updated_at with unique index on (field_name, option_value)
  • Added inpipe_seed_utm_options() function in install.php with INSERT IGNORE for idempotent re-activation
  • Added 3 new REST API endpoints: inpipe-utm-options-fetch, inpipe-utm-options-save, inpipe-utm-options-delete
  • Added handle_utm_options_fetch(), handle_utm_options_save(), handle_utm_options_delete() to InPipe_API_Endpoints_Free
  • Added UTM_OPTIONS_FETCH, UTM_OPTIONS_SAVE, UTM_OPTIONS_DELETE to frontend API_ENDPOINTS
  • Removed Gorilla tracking script from free build in vite.config.js (premium-only)
  • Table added to inpipe_cleanup_tables() for proper uninstall cleanup
  • Added editSnapshot, editingCodedValue, isLoadingEdit, highlightedUtmId, utmParamsCard reactive refs to UTM Coder component

1.1.0 – 2026-01-29

Gorilla Food REST API Endpoint, Cache-Busting & Hourly Usage Sync

NEW FEATURES

  • Hourly Usage Data Sync: inpipe_sync_subscription_data now fetches fresh usage data from Subscriber App API
    • Automatically updates inpipe_usage_data option with events_used_this_month, allowance, etc.
    • Updates inpipe_last_webhook timestamp so “Synced at” reflects actual sync time
    • No longer relies solely on Stripe webhook push – now actively pulls data hourly
  • Gorilla Food REST API Endpoint: Added /wp-json/inpipe/v1/gorilla-food endpoint for Safari ITP bypass on cached pages
    • Called by JavaScript when no gorilla_food cookie exists
    • Sets server-side cookie via PHP (bypasses Safari 7-day ITP limitation)
    • REST API endpoints bypass FastCGI page cache, ensuring PHP always executes
    • Returns gorilla_food visitor ID and is_new_user boolean

IMPROVEMENTS

  • Gorilla Food Cookie Optimization: Cookie now only set for new users

    • Prevents polluting page cache with Set-Cookie headers
    • Returning users already have the cookie – no need to re-set
    • Improves cache efficiency on high-traffic sites
  • Cache-Busting Page Reload: Improved page refresh after premium installation

    • Replaced window.location.reload() with cache-busting URL approach
    • Adds _inpipe_refresh timestamp parameter to force fresh HTML
    • Ensures premium CSS/JS loads correctly without manual hard refresh
    • Applied to both successful installation and timeout recovery flows
  • Renamed Frontend Tracking Script: Renamed tracking script to “Gorilla” for consistency

    • Script handle changed from inpipe-tracking to inpipe-gorilla
    • Script file renamed from tracking.js to gorilla.js
    • Backwards-compatible: window.initInPipeTracker aliased to window.initGorilla

TECHNICAL

  • Added handle_gorilla_food() method to InPipe_API_Endpoints_Free class
  • Registered new public REST route /inpipe/v1/gorilla-food with __return_true permission
  • Updated set_cookie() in InPipe_Gorilla_Food_Manager to skip returning users
  • Simplified cookie path to / for broader compatibility
  • Changed error logging to use inpipe_debug_log() helper
  • Removed redundant log_error() private method from Gorilla Food Manager
  • Updated inPipeSubscriptionComponent.vue reload logic with URL cache-busting
  • Renamed wp_enqueue_script handle from inpipe-tracking to inpipe-gorilla
  • Updated wp_localize_script to use new inpipe-gorilla handle

1.0.9 – 2026-01-20

Server-Side Cookie for Safari ITP Bypass (gorilla_food)

FIXES

  • Fixed duplicate error message display on subscription activation page
    • Removed redundant error display from inPipeBaseInput :error prop
    • Error now only shows once in the styled red-bordered box

NEW FEATURES

  • Gorilla Food Cookie System: Implemented server-side cookie system to bypass Safari ITP 7-day JavaScript cookie limitation

    • Server-side PHP setcookie() creates HTTP cookie that Safari treats as first-party
    • 400-day cookie expiration (maximum browser-allowed duration)
    • Unique 35-character visitor ID format: XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX
    • Uses 58-character set excluding confusing characters (O, o, l, 0)
  • Visitor Identification: New gorilla_food cookie provides persistent visitor identification

    • Survives Safari ITP cookie restrictions that limit JavaScript cookies to 7 days
    • Cookie refreshed on every page load to maintain freshness
    • Bot detection to skip cookie setting for crawlers
  • dataLayer Integration: Gorilla food value automatically pushed to dataLayer

    • gorilla_food – The unique visitor identifier
    • is_new_user – Boolean indicating if this is a new visitor (cookie just created)
    • Available at priority 1 in wp_head for all tracking scripts

NEW FILES

  • includes/core/cookie/index.php – Directory protection
  • includes/core/cookie/inpipe-gorilla-food-functions.php – Core generation functions and constants
  • includes/core/cookie/class-inpipe-gorilla-food-manager.php – Cookie management class
  • includes/core/cookie/class-inpipe-gorilla-food-integration.php – WordPress hooks and dataLayer output

TECHNICAL

  • Added INPIPE_COOKIE_NAME constant (gorilla_food)
  • Added INPIPE_COOKIE_EXPIRY constant (400 days)
  • Added INPIPE_COOKIE_ID_LENGTH constant (35 characters)
  • Added inpipe_generate_gorilla_food() function
  • Added inpipe_generate_random_string() function
  • Added inpipe_validate_gorilla_food() function
  • Added InPipe_Gorilla_Food_Manager class
  • Added InPipe_Gorilla_Food_Integration class with static access methods
  • Bootstrap runs at plugins_loaded priority 5
  • Cookie set at init priority 1 (before headers sent)
  • dataLayer output at wp_head priority 1

PREMIUM INTEGRATION

  • Premium plugin’s tracking.js now reads gorilla_food from dataLayer
  • All events include gorilla_food and is_new_user fields
  • PHP-collected events also include gorilla_food via InPipe_Gorilla_Food_Integration::get_gorilla_food()
  • Added inpipe_premium_build_event() helper function for building events with gorilla_food

1.0.8 – 2026-01-15

Redis Stale Cache Recovery

NEW FEATURES

  • Added refresh_settings() method to Settings Manager for Redis stale cache recovery
    • Force-reloads settings from database bypassing object cache
    • Used by Connections Manager when client_id appears empty due to stale Redis cache
    • Used by Usage Webhook Sender when subscription_key/subscription_status appear empty
    • Prevents “Valid client ID not found” error on Redis-enabled servers (e.g., Cloudways)
    • Ensures usage webhooks are scheduled and sent correctly even with stale cache

1.0.7 – 2026-01-13

Auto-Disable Event Tracking for Expired Subscriptions

NEW FEATURES

  • Automatic Event Tracking Disable: Event tracking is now automatically disabled when subscription is not active
    • Catches cases where subscription expired while site was offline
    • Runs on plugin initialization and when subscription status changes
    • Only active and trialing subscriptions can have event tracking enabled

IMPROVEMENTS

  • Subscription Data Always Available: Subscription data is now always included in admin settings, not just for active premium users
    • Enables proper display of expired/cancelled subscription status in UI
    • Allows users to see their subscription status even after it expires

UI ENHANCEMENTS

  • Toggle Component Disabled State: Added disabled prop support to base toggle component
    • Visual feedback with reduced opacity and grayscale filter
    • Prevents interaction when disabled
    • Proper ARIA accessibility attributes

BUG FIXES

  • Fixed Auto-Refresh After Premium Upgrade: Page now correctly auto-refreshes after successful premium installation
    • Backend was missing safe_to_refresh and require_refresh flags in API response
    • Frontend condition was always false, preventing the reload from triggering

CODE CLEANUP

  • Removed dead code from Settings Manager:
    • Removed unused $is_premium property
    • Removed unused validate_license() method (~75 lines)
    • Premium status now fully handled by InPipe_Status_Manager

TECHNICAL

  • Added maybe_disable_event_tracking() method to InPipe_Status_Manager
  • Updated on_subscription_changed() to auto-disable tracking when subscription becomes inactive
  • Modified get_vue_admin_settings() to always include subscription data
  • Enhanced inPipeBaseToggle.vue with disabled state styling and handling
  • Fixed handle_premium_install() response to include refresh flags
  • Updated class-inpipe-settings-manager.php – Removed stale-cache check, dead code cleanup

1.0.6 – 2026-01-08

Redis Object Cache Compatibility Fix

BUG FIXES

  • Fixed WordPress Hooks Not Registering on Redis Cache Hit: Hooks were incorrectly placed inside cache check blocks, causing them to not register when object cache returned a hit
    • WordPress hooks are request-specific and must be registered on every request
    • Cache was preventing add_action() and add_filter() calls from executing on cached requests
    • Fixes cron jobs not firing, REST API endpoints not registering, and event tracking not working on Redis/Memcached hosting

AFFECTED FILES

  • class-inpipe-utm-decoder.php – Fixed init_hooks() method
  • class-inpipe-premium-event-collector.php – Fixed register_wordpress_hooks(), register_pattern_based_hooks(), and initialize_form_protection() methods

TECHNICAL

  • Moved all add_action() and add_filter() calls outside of cache check if-blocks
  • Cache is now only used for debug logging purposes (first-init detection)
  • WordPress automatically deduplicates identical hook registrations, making this pattern safe
  • Compatible with all object cache backends: Redis, Memcached, APCu, and default (no cache)

1.0.5 – 2026-01-06

Trial Subscription Support & REST API Fix

NEW FEATURES

  • Trial Subscription Status Support: Added full support for trialing subscription status from Stripe
    • Trial users now properly recognized as premium users with access to all features
    • Premium UI components display correctly during trial period
    • Event tracking enabled for trial subscriptions

UI ENHANCEMENTS

  • Trial Status Display: Added “Trial Active” status display in subscription management
    • New blue badge styling for trial status (.badge-trialing)
    • Status indicator shows “Trial Active” instead of “Unknown”
    • Consistent visual styling across all subscription status displays

BUG FIXES

  • Fixed REST API 404 Errors on Cached Servers: Removed incorrect route caching that caused 404 errors on servers with persistent object cache (Redis/Memcached)
    • Routes must be registered on every rest_api_init call; caching was preventing registration
    • Fixes /wp-json/inpipe/v1/* endpoints returning 404 on cached hosting environments
  • Fixed Premium Detection for Trials: Trial subscriptions now correctly detected as valid premium subscriptions
    • Updated isValid() method to accept trialing status
    • Updated inpipe_has_premium_subscription() SQL query to include trialing
    • Fixed is_active checks in API endpoints to recognize trial subscriptions
  • Fixed Subscription Warning Banner: Trial users no longer see incorrect subscription warning messages
  • Fixed Event Tracking for Trials: Event tracking now properly schedules for trial subscriptions

TECHNICAL

  • Updated class-inpipe-status-manager.php with trialing status support
  • Updated class-inpipe-api-endpoints-free.php with trialing status checks and removed route caching
  • Added @since 1.0.5 documentation tags to all modified methods

1.0.4 – 2025-12-16

Subscription Type Fix & Webhook Improvements

BUG FIXES

  • Fixed Subscription Type Mapping: Subscription type now correctly reads from API response
    • Changed from metadata_plan_name to plan_name field to match actual API response
    • Fixes issue where subscription_type was defaulting to “free” after premium upgrade
    • Supported plan types: Trial, Entry, Premium, Professional, Enterprise

IMPROVEMENTS

  • Simplified Webhook Handler: Refactored handle_subscription_webhook() to use action hook pattern
    • Now delegates webhook processing to Premium plugin via inpipe_process_webhook action hook
    • Cleaner separation between Free and Premium plugin responsibilities
    • Premium plugin hooks in with: add_action('inpipe_process_webhook', [$this, 'process_webhook'], 10, 3)

1.0.3 – 2025-12-01

CRITICAL Uninstall Fix + Security Improvements + UI Fixes

BUG FIXES

  • Fixed Subscription Code Whitespace: Subscription codes with leading/trailing spaces now validate correctly
    • Added trim() to subscription code input before validation and API submission
    • Prevents “Invalid subscription code format” error when users paste codes with extra whitespace

UI ENHANCEMENTS

  • Mobile Responsive Buttons: Fixed upgrade buttons in Settings component for mobile view
    • Buttons now …
Back to top