Title: inPIPE by Seresa
Author: Seresa
Published: <strong>7 July 2025</strong>
Last modified: 2 September 2026

---

Search plugins

![](https://ps.w.org/inpipe-by-seresa/assets/icon-128x128.png?rev=3323178)

# inPIPE by Seresa

 By [Seresa](https://profiles.wordpress.org/seresa8/)

[Download](https://downloads.wordpress.org/plugin/inpipe-by-seresa.2.0.5.zip)

 * [Details](https://en-gb.wordpress.org/plugins/inpipe-by-seresa/#description)
 * [Reviews](https://en-gb.wordpress.org/plugins/inpipe-by-seresa/#reviews)
 *  [Installation](https://en-gb.wordpress.org/plugins/inpipe-by-seresa/#installation)
 * [Development](https://en-gb.wordpress.org/plugins/inpipe-by-seresa/#developers)

 [Support](https://wordpress.org/support/plugin/inpipe-by-seresa/)

## 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](https://support.seresa.io/docs/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
 2.  * 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](https://seresa.io/terms) and [Privacy Policy](https://seresa.io/privacy)
 3. Package Installation
 4.  * 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](https://seresa.io/terms) and [Privacy Policy](https://seresa.io/privacy)
 5. Transmute Engine (Premium Feature)
 6.  * 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](https://seresa.io/terms) and [Privacy Policy](https://seresa.io/privacy)

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
 2.   * What: A progressive JavaScript framework for building user interfaces
      * Website: https://vuejs.org/
      * License: MIT License – https://github.com/vuejs/vue/blob/main/LICENSE
 3.  Vue Toastification
 4.   * What: Toast notification library for Vue.js
      * Website: https://github.com/Maronato/vue-toastification
      * License: MIT License
 5.  Lucide Icons
 6.   * What: Beautiful & consistent icon toolkit for Vue.js
      * Website: https://lucide.dev/
      * License: ISC License – https://github.com/lucide-icons/lucide/blob/main/LICENSE
 7.  Axios
 8.   * What: Promise-based HTTP client for JavaScript
      * Website: https://axios-http.com/
      * License: MIT License
 9.  Pinia
 10.  * What: State management library for Vue.js
      * Website: https://pinia.vuejs.org/
      * License: MIT License
 11. Vue I18n
 12.  * What: Internationalization plugin for Vue.js
      * Website: https://vue-i18n.intlify.dev/
      * License: MIT License
 13. Tailwind CSS
 14.  * What: Utility-first CSS framework
      * Website: https://tailwindcss.com/
      * License: MIT License
 15. WordPress JavaScript Libraries
 16.  * 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](https://github.com/seresa8/inPIPE-by-Seresa-issues/issues)

For **general inquiries**, contact us at [support@seresa.io](https://en-gb.wordpress.org/plugins/inpipe-by-seresa/support@seresa.io?output_format=md).

For **premium users**: Get priority support at 🔗 [seresa.io/support](https://seresa.io/support).

## Installation

 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.

## FAQ

### 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](https://support.seresa.io/docs/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](https://support.seresa.io/docs/inpipe-utm-api-documentation)

## Reviews

![](https://secure.gravatar.com/avatar/f079c2a396d18b1ae8f735d18beebb3073ff6000379d4a299fce65a1b3560acd?
s=60&d=retro&r=g)

### 󠀁[Premium version](https://wordpress.org/support/topic/premium-version-85/)󠁿

 [ender015](https://profiles.wordpress.org/ender015/) 7 July 2025 1 reply

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!

 [ Read all 1 review ](https://wordpress.org/support/plugin/inpipe-by-seresa/reviews/)

## Contributors and Developers

“inPIPE by Seresa” is open source software. The following people have contributed
to this plugin.

Contributors

 *   [ Seresa ](https://profiles.wordpress.org/seresa8/)

[Translate “inPIPE by Seresa” into your language.](https://translate.wordpress.org/projects/wp-plugins/inpipe-by-seresa)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/inpipe-by-seresa/),
check out the [SVN repository](https://plugins.svn.wordpress.org/inpipe-by-seresa/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/inpipe-by-seresa/)
by [RSS](https://plugins.trac.wordpress.org/log/inpipe-by-seresa/?limit=100&mode=stop_on_copy&format=rss).

## Change Log

#### 2.0.5 – 2026-09-02

**Compatibility: verified against WordPress 7.1**

#### COMPATIBILITY

 * **Tested up to WordPress 7.1**: Plugin activation, the full `inpipe/v1` REST 
   surface, and the admin UI were exercised on WordPress 7.1 (PHP 8.3) with no deprecations,
   warnings, or errors
 * **Minimum WordPress raised to 6.5**: The supported floor moves up alongside the
   tested ceiling; PHP 8.3 remains the minimum

#### 2.0.4 – 2026-08-09

**Bug fix: encrypted values could fail to decrypt on some Lightspeed hosts**

#### BUG FIXES

 * **Stored secrets (e.g. API keys) now decrypt reliably on hosts without native
   libsodium**: On servers where libsodium runs through the pure-PHP polyfill (seen
   on some Lightspeed hosts), the secure key-wipe step threw an error that aborted
   the entire decrypt, so encrypted values could not be read back (for example, 
   a saved API key was reported as “not configured”)
    - The key-wipe (`sodium_memzero`) is memory hygiene, not part of the encrypt/
      decrypt result; a failure there is now caught and no longer breaks encryption
      or decryption

#### TECHNICAL

 * Added `InPipe_Encryption::safe_memzero()` — wraps `sodium_memzero()` and falls
   back to overwriting the key variable when the polyfill cannot securely wipe memory,
   so `encrypt()`/`decrypt()` succeed regardless of the libsodium implementation

#### 2.0.3 – 2026-07-24

**Bug fix: broken admin styles after upgrading to Premium (stale cached CSS)**

#### BUG FIXES

 * **Admin UI no longer loads stale CSS after a Premium upgrade**: The settings 
   screen now pulls the real stylesheet directly, so the new styles appear immediately
   instead of requiring a manual browser/CDN cache clear
    - The admin styles were enqueued through a build-generated redirect stub (`inPipeAdmin.
      css`) that only did `@import './inPipeMain.css';`. WordPress applied the cache-
      busting version to the stub, but the imported `inPipeMain.css` — which actually
      contains the styles — was requested with no version query, so browsers and
      CDNs kept serving the old cached bundle after the upgrade
    - The admin stylesheet now enqueues `inPipeMain.css` directly, so the `inpipe_assets_version`
      cache-buster applies to the file that holds the CSS

#### TECHNICAL

 * `enqueue_admin_assets()` in `class-inpipe-vue-admin.php` now registers `dist/
   css/inPipeMain.css` instead of the `dist/css/inPipeAdmin.css` redirect stub, 
   keyed to `inpipe_assets_version`
 * No change to what styles are shipped — only which file WordPress requests, so
   the version query busts the actual bundle

#### 2.0.2 – 2026-07-20

**Database schema support for the premium Harvest Lite trial**

#### TECHNICAL

 * Added a `data_access_key` column to the `wp_inpipe_pluginsettings` table to store
   the read-only data key issued to premium Harvest Lite trial sites
 * Bumped the internal database schema version so existing installs add the new 
   column automatically on update (via dbDelta), rather than only on a fresh activation
 * No changes to free-plugin behavior, UTM tracking, the admin UI, or any stored
   data

#### 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

#### Earlier versions

Changelog entries for the 1.x releases have been trimmed to keep this readme tidy.
The full history remains available in the plugin’s SVN tags: https://plugins.svn.
wordpress.org/inpipe-by-seresa/tags/

## Meta

 *  Version **2.0.5**
 *  Last updated **1 month ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.5 or higher **
 *  Tested up to **7.1.3**
 *  PHP version ** 8.3 or higher **
 *  Language
 * [English (US)](https://wordpress.org/plugins/inpipe-by-seresa/)
 * Tags
 * [datalayer](https://en-gb.wordpress.org/plugins/tags/datalayer/)[Server Side Tracking](https://en-gb.wordpress.org/plugins/tags/server-side-tracking/)
   [utm tracking](https://en-gb.wordpress.org/plugins/tags/utm-tracking/)
 *  [Advanced View](https://en-gb.wordpress.org/plugins/inpipe-by-seresa/advanced/)

## Ratings

 5 out of 5 stars.

 *  [  1 5-star review     ](https://wordpress.org/support/plugin/inpipe-by-seresa/reviews/?filter=5)
 *  [  0 4-star reviews     ](https://wordpress.org/support/plugin/inpipe-by-seresa/reviews/?filter=4)
 *  [  0 3-star reviews     ](https://wordpress.org/support/plugin/inpipe-by-seresa/reviews/?filter=3)
 *  [  0 2-star reviews     ](https://wordpress.org/support/plugin/inpipe-by-seresa/reviews/?filter=2)
 *  [  0 1-star reviews     ](https://wordpress.org/support/plugin/inpipe-by-seresa/reviews/?filter=1)

[Your review](https://wordpress.org/support/plugin/inpipe-by-seresa/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/inpipe-by-seresa/reviews/)

## Contributors

 *   [ Seresa ](https://profiles.wordpress.org/seresa8/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/inpipe-by-seresa/)