Description
Joryio connects any WordPress site to the Joryio marketing automation platform (a hosted service – you need a Joryio account). On every site it tracks page views, sends Contact Form 7 and Elementor Pro form submissions to Joryio, and shows Joryio in-app messages and web push. With WooCommerce active it also syncs your products, orders and customers and powers abandoned cart recovery.
Nothing is sent to Joryio until you connect the plugin with your Joryio API key. What is sent, and when, is listed under “External services” below.
Key Features
On any WordPress site:
- Page tracking – Page views and visitor activity reach Joryio through the tracking script
- Website forms – Send Contact Form 7 and Elementor Pro form submissions to Joryio: the contact is created or updated, a “Form Submitted” event is recorded, and each form decides whether it subscribes the contact (a signup form with its subscribe switch on and the consent text it shows, or only when its consent box is ticked)
- In-app messages and web push – Show Joryio in-app messages (popups) on your site and let visitors subscribe to browser notifications
With WooCommerce:
- Abandoned Cart Recovery – Automatically track and recover abandoned carts with personalized email campaigns
- Customer Identity Tracking – Capture customer emails early in the shopping journey
- Real-time Data Sync – Products, orders, and customers sync automatically to Joryio
- Cart Recovery Links – One-click cart restoration for returning customers
- UTM Tracking – Capture marketing attribution data for better campaign analysis
- Marketing Consent Checkbox – Collect email (and optionally SMS) opt-ins on checkout and registration, with the evidence recorded on each order
How It Works
- Install the plugin from Plugins > Add New Plugin (search for “Joryio”) and activate it
- In your Joryio dashboard, go to Settings > Integrations > WooCommerce & WordPress and copy the server URL and API key
- Paste them in the plugin settings (WooCommerce > Joryio on a store, Settings > Joryio on a site without WooCommerce) and click Connect
- A store syncs automatically; a site without WooCommerce starts sending page tracking, forms, in-app messages and web push
Abandoned Cart Tracking
The plugin tracks cart contents in real-time. When a customer adds items to their cart, their session is tracked. If they leave without completing their purchase, Joryio can send automated recovery emails with a personalized link to restore their cart.
Customer Identity
The plugin captures customer emails from:
* Checkout form
* Account registration
* Newsletter signup forms
* Any email input field
This allows Joryio to associate cart data with customer profiles for personalized marketing. You can turn off “Recognise visitors by the email they type” in the settings so that only signed-in customers are recognised.
Your visitors’ privacy and consent
- The plugin contacts Joryio only after you connect it with your API key, and stops when you disconnect.
- The tracking script can be turned off in the settings (“Inject Tracking Script”); in-app messages and web push have their own settings, and web push is off until you turn it on. A visitor is asked by their browser before any push notification is shown.
- The marketing consent checkbox (checkout and registration, off until you turn it on) records what the shopper saw and chose on the order. A box ticked by default counts only after the shopper touches it, and by default the opt-in counts only when the order is placed.
- Website forms subscribe a contact only as each form is set up: a signup form with its subscribe switch on and the consent text it shows (otherwise no subscription), or only when its consent box is ticked.
- You are the controller of your visitors’ data. Mention Joryio in your site’s privacy policy and, where your visitors’ law requires it, ask for cookie consent before the tracking script runs (for example with a cookie consent plugin that holds back scripts until consent is given).
The storefront sets these first-party cookies: joryio_client_id (an anonymous visitor id, 1 year), joryio_session (the cart session, 30 days), joryio_email (an email the visitor typed, kept in their own browser, 30 days), joryio_utm_*, joryio_jr_cid and joryio_jr_jid (the campaign and message ids of a Joryio link they followed, 30 days), joryio_li (a random value telling the storefront the sign-in changed, no user data) and joryio_pending (a short-lived flag for add-to-cart events).
Source code
The plugin ships as readable source, with no build step and nothing minified. The web SDK it loads from sdk.joryio.com is Joryio’s hosted JavaScript library for the service (see “External services”).
Requirements
- WordPress 6.0 or higher
- WooCommerce 5.0 or higher for the store features (cart, orders, products, coupons, checkout consent). Without WooCommerce the plugin still connects your site for website forms, the tracking script, in-app messages and web push
- Contact Form 7, or Elementor Pro, for website forms (optional)
- PHP 7.4 or higher
- A Joryio account
External services
This plugin connects your site to Joryio, a hosted marketing automation service run by Joryio. It is needed for everything the plugin does: the plugin is an interface to your Joryio account. Nothing is sent before you click Connect with your Joryio API key, and nothing is sent after you click Disconnect.
Joryio terms of service: https://www.joryio.com/legal/terms-of-service
Joryio privacy policy: https://www.joryio.com/legal/privacy-policy
Data processing agreement: https://www.joryio.com/legal/dpa – subprocessors: https://www.joryio.com/legal/subprocessors
1. Joryio API (your region’s server, for example https://api-eu1.joryio.com or https://api-us1.joryio.com)
The server URL you paste when you connect. Requests go from your site’s server, and from your visitors’ browsers for the storefront events:
- When you connect, test or disconnect: your API key, the site URL and name, the WordPress, WooCommerce and plugin versions, the site’s time zone and (on a store) currency. On a store, the plugin creates a WooCommerce REST API key (“Joryio Integration”, read/write) and sends it to Joryio, which uses it to read your products, orders, customers and coupons, to register its WooCommerce webhooks and to create the coupon codes your campaigns use. Disconnect deletes that key and the webhooks.
- When store data changes (WooCommerce): products (name, price, images, categories, stock), orders (items, totals, payment method and status, the customer’s name, email, phone and addresses, the consent the shopper gave (the wording of the box, the page and the shopper’s IP address)), customers (email, name, phone, addresses, order history) and carts (contents, the shopper’s email when known, the recovery link, and for a guest the anonymous visitor id from the shopper’s own cookie).
- On storefront pages (tracking script, when it is on): page views, product and category views, add to cart, checkout started, and the anonymous visitor id; an email address the visitor types in a form or at checkout (and the name typed with it at checkout), unless “Recognise visitors by the email they type” is off; for a signed-in customer, a signed proof of their customer id.
- When a website form is submitted (Contact Form 7, Elementor Pro): the fields you map in the form’s Joryio settings, the form’s name and page, the consent box when the form has one, (1.6.38) the channels you chose for the form’s consent, and (1.6.39) a signup form’s consent text. When the form’s consent box is ticked, or a signup form has its consent text (1.6.41), also that wording and the submitter’s IP address, kept by Joryio as consent evidence. When the person submitting is a logged-in customer (1.6.34), a signed proof of their customer id, made for that one submission, so Joryio can let the form update that customer’s own phone number. The settings page and the Elementor editor also read your Joryio lists and attribute names (names and types only, no contact data) for the form setup.
- When a shopper ticks or unticks the checkout opt-in (with “Record consent immediately”): the box, its new value, the session’s email and the shopper’s IP address, kept by Joryio as consent evidence.
- With every request: your plugin settings that Joryio follows or shows on your store’s page: the checkout opt-in settings, “Recognise visitors by the email they type”, “Track guest carts” and the abandonment time.
2. Joryio web SDK (https://sdk.joryio.com)
When in-app messages (on by default) or web push (off by default) are on, the storefront loads Joryio’s JavaScript library from https://sdk.joryio.com/web/1/joryio.min.js in the visitor’s browser. It shows the in-app messages you publish in Joryio (with “Allow HTML in-app messages” on, messages built with the HTML editor are shown in a separate frame whose Content Security Policy blocks every script written into them; they can show images, fonts and video loaded over HTTPS, but cannot run code on your pages, fetch data or submit forms themselves) and, with web push on, asks the visitor for permission and registers the browser for push notifications. It sends the anonymous visitor id, the messages shown and clicked, and the browser’s push subscription to your Joryio API server. With web push on, the service worker at /joryio-sw.js on your site loads https://sdk.joryio.com/web/1/joryio-sw.js to show the notifications.
Links in the emails and messages Joryio sends (for example cart recovery and coupon links) point back to your site; when you set up click tracking in Joryio they pass through Joryio’s tracking domain first. The plugin itself does not contact that domain.
Screenshots



Installation
- In WordPress, go to Plugins > Add New Plugin, search for “Joryio”, click Install Now and then Activate. (Or download the zip from the Joryio dashboard – Settings > Integrations > WooCommerce & WordPress > Download zip – and upload it under Plugins > Add New Plugin > Upload Plugin.)
- Go to WooCommerce > Joryio in your WordPress admin (Settings > Joryio on a site without WooCommerce)
- Copy the server URL and API key from your Joryio dashboard (Settings > Integrations > WooCommerce & WordPress)
- Paste both and click Connect
- A store syncs automatically with Joryio. Your settings are on the tabs of the same page (Tracking & identity, Store, Consent, In-app & web push, Forms); on a site without WooCommerce, set up your forms on the Forms tab
Updating
WordPress updates the plugin like any other plugin from the plugin directory. A copy uploaded from the Joryio dashboard zip is the same plugin in the same folder, so it gets the same updates. Settings and the connection are kept.
FAQ
-
Do I need a Joryio account?
-
Yes, you need a Joryio account to use this plugin. Sign up at joryio.com.
-
Do I need WooCommerce?
-
No. Without WooCommerce the plugin connects your site for page tracking, website forms (Contact Form 7, Elementor Pro), in-app messages and web push. The store features (product, order and customer sync, abandoned carts, coupons, the checkout consent checkbox) turn on with WooCommerce. If you add WooCommerce later, disconnect and connect again so Joryio can sync your store.
-
What data is synced to Joryio?
-
On a WooCommerce store the plugin syncs:
* Products (name, price, images, categories, stock status)
* Orders (items, totals, customer info, shipping/billing addresses)
* Customers (email, name, order history)
* Abandoned carts (cart contents, customer email if known) -
Is customer data secure?
-
All data is sent to Joryio over HTTPS. What is sent, and when, is listed under “External services”; how Joryio handles it is in the Joryio privacy policy (https://www.joryio.com/legal/privacy-policy).
-
No. The plugin does not show a cookie banner. Where your visitors’ law requires consent before tracking, use a cookie consent plugin that holds back scripts until the visitor agrees, or turn off “Inject Tracking Script” in the settings. The marketing consent checkbox at checkout is a separate thing: it records whether a shopper agreed to receive marketing.
-
Will this slow down my site?
-
No, the plugin is designed to be lightweight. Store data is sent in the background (WP-Cron); a cart change, and the abandoned-cart check, are sent at the end of the visit, after the page is sent on PHP-FPM and LiteSpeed servers.
-
How do I run the abandoned-cart check by hand?
-
Run
wp cron event run --due-now(WP-CLI), or requesthttps://your-store/wp-cron.phpwithout adoing_wp_cronvalue. A request that carries adoing_wp_cronvalue runs nothing unless the value is exactly WordPress’s own current lock. What the check reported is in WooCommerce > Status > Logs, source “joryio”. -
How long before a cart is considered abandoned?
-
By default, a cart is considered abandoned after 30 minutes of inactivity. You can change it under WooCommerce > Joryio > Store (“Cart Abandonment Time”).
-
Does it work with a page cache?
-
Yes. The tracking script is the same on every page and holds nothing about the visitor (no email, session or user id), so a page cache (Breeze, WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache, WP Fastest Cache, SiteGround Optimizer, Cloudflare) may store it. Who is signed in is asked by the script itself, through a request that is never cached. A page cached before you connected has no Joryio script: the plugin empties the cache of those plugins when you connect, disconnect, change the tracking settings or update the plugin. With any other cache (a host’s server cache, Varnish, a CDN), purge it yourself after connecting.
-
Can I use this with other marketing plugins?
-
Yes, Joryio works alongside other plugins. There are no known conflicts.
Reviews
There are no reviews for this plugin.
Contributors & Developers
“Joryio – Marketing Automation for WooCommerce” is open source software. The following people have contributed to this plugin.
ContributorsTranslate “Joryio – Marketing Automation for WooCommerce” into your language.
Interested in development?
Browse the code, check out the SVN repository, or subscribe to the development log by RSS.
Changelog
1.6.41
- Signup forms now need the consent text to subscribe on any channel, email included – forms without it are listed on the Joryio page. A signup form (no consent checkbox) has a new switch, off by default: “Subscribe visitors when they submit this form (no consent checkbox)” – use it only if the form shows a sentence telling visitors they agree to receive messages. Off: the form saves the contact and records the Form Submitted event but subscribes nobody. On: its channels (or its list) and, right under them, “Consent text shown on this form (required)” – the exact sentence visitors see. With the text, every selected channel, email included, is subscribed and the text recorded as the proof (form text, not a ticked box); without it nobody is subscribed. SMS, WhatsApp and Viber still need a phone field. One rule for every channel, because the text is the proof of what the visitor saw and agreed to
- IMPORTANT for existing signup forms: the update turns the switch on for a signup form that has a consent text, or had “Also subscribe SMS / WhatsApp / Viber without a consent checkbox” on – its channels and text are kept (with that option off, its SMS, WhatsApp and Viber, which never subscribed, are taken out of its channels). A signup form with no consent text – including an email-only one that subscribed on every submission – is switched off and subscribes nobody until you turn it on and add the text. Each such form is named in an admin notice on the Plugins screen and the Joryio page, and each of its submissions is logged. A form whose switch is on but has no text gets a warning in its settings, the notice and a log line
- The “Also subscribe SMS / WhatsApp / Viber without a consent checkbox” option (1.6.39) is gone. A signup form with a list keeps the list
- Forms with a consent checkbox are unchanged: the ticked box is the consent and its label is the wording
- Web SDK: the site’s Web push setting is passed to the SDK (webPush), so a visitor’s push permission is reported to Joryio only on a site that uses web push
- Web SDK (in-app messages, web push): with the browser’s storage blocked, the tracker’s visitor id is a shared placeholder and the web SDK made up a new id of its own on every page – one empty profile per page view. It is no longer started when storage is blocked. And when the tracker starts a new visitor id (log out, another customer signs in), the running SDK is first reset (the previous person’s user id, attributes, in-app state and push binding are dropped, as before), then restarted with the tracker’s new id instead of keeping a random one of its own, so the two stay one visitor
- Readme: the install steps name the dashboard’s “Download zip” button and WordPress’s “Add New Plugin” screen
1.6.40
- The plugin’s name is now “Joryio – Marketing Automation for WooCommerce” (it was “Joryio”). It runs on any WordPress site as before, with or without WooCommerce. Nothing else changes: the same folder, settings, connection and updates
- Website forms: a consent box’s wording is cleaned with WordPress’s own wp_strip_all_tags() (WordPress Plugin Check). The text recorded is the same as before
1.6.39
- Website forms: a signup form (no consent box) can carry the consent line its visitors see – “Consent text shown on this form”. It is recorded as the consent wording with every subscription the form makes, marked as form text (consentMethod form_text; a ticked box is checkbox) on the consent record, the subscription history and the Form Submitted event, so the two kinds of proof can always be told apart
- New per-form option, off by default: “Also subscribe SMS / WhatsApp / Viber without a consent checkbox, using the text above as proof”. On, with a text entered, a signup form may subscribe the phone channels of a contact who never unsubscribed. A ticked box is the strong proof SMS and WhatsApp marketing require; text-only consent is weaker – Joryio cannot prove the visitor saw the text. Check the wording with your lawyer (in Israel, section 30A of the Communications Law; Meta’s WhatsApp opt-in policy)
- Unchanged: a phone is required; a form text never re-subscribes someone who unsubscribed and never lifts a STOP, a complaint, a hard bounce or a staff block; SMS double opt-in still applies; an opt-out made by another contact with the same email or phone is not lifted. Needs a Joryio release from 2026-11-09 or later: an older Joryio refuses a submission that carries the form text, and that submission is not recorded. A form without a text is sent exactly as before
1.6.38
- Website forms: consent now subscribes the contact on channels too. With a list, the consent covers the list’s channels exactly as the list is set up in Joryio (for example Email and SMS), and the form settings say “This list covers: …” so the two never disagree. With “No list”, choose the channels under “Consent subscribes to channels”: Email, SMS, WhatsApp, Viber (web push is not offered – browsers ask for it themselves)
- In “Only when a consent field is ticked” mode, ticking the box subscribes those channels; in “This is a signup form – always subscribe” mode, submitting does. SMS, WhatsApp and Viber need a phone field and a ticked consent field with its wording, so a signup form subscribes Email only
- Someone who unsubscribed (from the channel or the list) or whose email or phone is opted out and now ticks the consent field is subscribed again at once by default; the wording, page, time and IP address are recorded and the change is marked as a re-subscribe (channelsResubscribed, listsResubscribed). That proves the submission, not who typed the address; direct re-subscribe is the deliberate default (2026-11-09) and covers the contact’s own unsubscribe only – an opt-out recorded by another contact sharing the email or phone is never lifted by a form (Email gets the confirmation email, SMS, WhatsApp and Viber are not subscribed)
- New per-form option, off by default: “Send a confirmation email before re-subscribing someone who unsubscribed”. On: Email waits for a click on a confirmation email (at most one a day; channelsPending, reason confirmation_sent) and SMS, WhatsApp and Viber are not re-subscribed (needs_confirmation). A signed-in customer of your store (the form carries the plugin’s signed proof) is re-subscribed directly either way
- Never, whatever the option: a signup form (no consent box) re-subscribing anyone, or a form lifting an SMS STOP or other keyword opt-out, a spam complaint, a hard bounce or a block set by Joryio staff
- A list’s channels each go through the same checks; a double opt-in list’s confirmation email subscribes its Email channel only
- Each channel’s subscription history in Joryio shows the proof (wording, page, time, IP address), and the Form Submitted event carries channelsSubscribed, channelsPending, channelsPendingReason, channelsResubscribed and listsResubscribed. Needs a Joryio release from 2026-11-09 or later: an older Joryio refuses a submission that carries channels, and that submission is not recorded. A form with no channels chosen is sent exactly as before
1.6.37
- Website forms: pick instead of typing. Contact Form 7’s attribute box and Elementor’s new “Custom attributes” rows list your Joryio attributes with their type (names and types only, read from Joryio and kept for ten minutes); you can still type a new name. “Refresh lists and attributes from Joryio” (Contact Form 7) and “Refresh attributes from Joryio” (Elementor) read them again. When Joryio cannot be reached, the box is a plain text box, as before
- Elementor: each field box (Email, Phone, First name, Last name, Consent field ID, and each custom attribute’s Form field) lists this form’s own fields by label and type and stores the field’s ID; you can still type an ID. A form saved earlier keeps its field IDs exactly as they are
- “Suggest from this form” (Elementor) and “Suggest from the field types and names” (Contact Form 7) fill the empty boxes from the field types and labels (an email field as Email, a phone field as Phone, First name / Last name labels in English and Hebrew). Nothing is saved until you click Update or Save form settings
- Elementor: custom attributes are now rows (Joryio attribute + Form field). Lines saved before 1.6.37 keep working and are shown under “Custom attributes (saved as lines)” until you empty that box
- Contact Form 7: the mapping table shows each field’s type and placeholder next to its name
- Elementor: the Joryio action’s field IDs and attribute rows are cleaned when the page is saved (an ID keeps only letters, digits, _ and -; an attribute name follows the attribute name rule), and the row titles in the panel show them as text
1.6.36
- Website forms: a custom attribute’s name is now kept exactly as typed when it already is a valid Joryio attribute name (letters, digits and underscores, starting with a letter, at most 64 characters). Type it as Joryio shows it under Data > Attributes:
vipTiernow writes vipTier. Until now every name was lower-cased, sovipTiersilently wrote a second attribute, viptier. Other text is still turned into a lower case name, as before (Company name becomes company_name) - A Contact Form 7 mapping saved before 1.6.36 keeps working unchanged: it was saved in lower case and keeps writing the lower case attribute (viptier). Nothing is rewritten. To write the camelCase attribute instead, type the name again as Joryio shows it and click Save form settings
- Elementor reads its “Custom attributes” lines as typed on every submission, so a line written with capitals (
vipTier = field_1) writes vipTier from this version on (it wrote viptier before). To keep writing the old attribute, type the name in lower case - A custom attribute named email, phone, firstName or lastName (any case, with or without underscores) now maps the field to the contact’s own email, phone or name, the same as choosing it under “Send as”, instead of writing a second attribute. The email and phone rules are unchanged: a form only fills an empty email or phone of an existing contact (a signed-in customer may update their phone, as since 1.6.34)
- Names Joryio manages itself can no longer be written by a form: predictions (ml_…), activity and device fields (lastEventName, os, …), externalId, and any name starting with $. Contact Form 7 says which ones were not saved; Elementor skips them and notes it in the plugin log. Joryio also ignores these names from older plugin versions
1.6.35
- The web push service worker is now served by WordPress itself at the same address, /joryio-sw.js, generated from your settings. The plugin no longer writes any file to your site folder (WordPress.org review). Browsers that already subscribed keep working: the address is unchanged
- The joryio-sw.js file an earlier version wrote to your site folder is deleted once by this update, and only when it is exactly the file the plugin wrote; a file you changed is left alone
- Some web servers answer .js addresses themselves and never pass a missing file to WordPress. With web push on, the In-app & web push tab now checks the address and says so; ask your host to pass /joryio-sw.js to WordPress
- The storefront’s calls to your site (the typed email, the signed-in customer proof, the queued add-to-cart events) now also carry a WordPress nonce. It is never printed into the page, so full-page caches keep working: the tracking script asks for a fresh one when it needs it
- Saving a settings tab now needs the same permission that opens the page (Manage WooCommerce on a store), and the registration consent box checks the registration form’s own nonce
- The plugin’s admin notices (no API key saved, reconnect after WooCommerce was activated) now show only on the Plugins screen and the Joryio settings page, to users who can act on them. The reconnect notice can be dismissed; the choice is kept per user. Nothing else changes
1.6.34
- A signed-in customer can update their phone number through a website form. When a logged-in customer submits a Contact Form 7 or Elementor form, the plugin now sends a signed proof of who is logged in (the same signed proof the storefront sign-in uses, made on your server and good for that one submission only). When the form’s email belongs to that same customer’s contact in Joryio, the phone typed into the form replaces the contact’s phone; the email never changes this way
- A visitor who is not logged in changes nothing that is already there: the form fills an empty email or phone only, as before. The proof is sent only for a form submitted on your own site (a form posted from another site in the customer’s browser gets none)
- The form’s email and phone are kept on the Form Submitted event in Joryio, so a different phone a visitor typed is no longer lost; the event says whether the contact took it
- Needs a Joryio release later than 2026-11-03 (an older Joryio refuses the new field, and that submission is not recorded); nothing to configure
- A Contact Form 7 form that submits through the WordPress REST API without the REST nonce is seen by WordPress as logged out; it sends no proof and the visitor rule applies
- On a WordPress site without WooCommerce, the In-app & web push settings tab now says “your site” and “visitors” instead of “your store” and “shoppers”
- The “External services” section of the readme now lists everything sent: a ticked form consent box’s wording and the submitter’s IP address (since 1.6.31), the wording, page and IP address with an order’s consent, and the signed-in customer proof sent with a form (1.6.34)
- The “Allow HTML in-app messages” help text and the readme now say exactly what an HTML message can do: it is shown in a separate frame whose Content Security Policy blocks every script written into it; it can show images, fonts and video loaded over HTTPS, but cannot run code on your pages, fetch data or submit forms itself
Earlier versions: see changelog.txt in the plugin folder.
