Skip to main content

Klaviyo Integration

Overview​

Klaviyo Integration sends the store's activity to Klaviyo so its email and SMS flows can act on it. Three things move: events (a product viewed, added to cart, an order placed, cancelled or refunded), profiles (the customer record, with consent), and the catalogue (products, so Klaviyo can render them in an email).

What distinguishes this module from a simple webhook is that delivery is treated as unreliable. Every event is queued in a local table with an idempotency key, a status, an attempt count and a next-retry time, and a retry job works the failures. Klaviyo's response is stored against the event, so a failure can be diagnosed rather than guessed at.

Consent is modelled explicitly: the profile mapping records email and SMS consent separately.

It is for stores running their marketing in Klaviyo.

Availability​

ItemValue
Module keyklaviyo
TierPremium
Entitlement keyklaviyo
Admin tabklaviyo
Enabled optionaiowc_module_enabled_klaviyo (off until turned on)
REST namespaceaiowc/v1

registerHooks() registers the REST routes and the jobs, then registers the WooCommerce event listeners only when the store is connected. That is the right shape: with no credentials, no store events are captured and no queue builds up behind a connection that does not exist.

Settings​

Settings are read and written through GET/POST /klaviyo/settings. Credentials are held in a dedicated credential repository rather than alongside ordinary settings.

Events​

The listener captures these WooCommerce and WordPress events:

HookWhat it means to Klaviyo
woocommerce_add_to_cartA product was added to a cart.
woocommerce_checkout_initA checkout was started.
woocommerce_checkout_order_processedAn order was placed.
woocommerce_order_status_completedAn order completed.
woocommerce_order_status_cancelledAn order was cancelled.
woocommerce_order_status_refundedAn order was refunded.
woocommerce_created_customerA customer account was created.
woocommerce_customer_save_address, profile_updateA customer's details changed.

Each becomes a row carrying its type and name, the customer's email and id, the payload as JSON, and an idempotency key. The key is what stops a re-fired hook or a retried job recording the same event twice in Klaviyo.

Delivery and retries​

An event's status is pending, sent, failed or retrying, with an attempt count, the time of the last attempt and the time of the next. A send job drains the queue and a retry job works the failures, storing the error message and Klaviyo's own response against the row.

Retries can also be driven by hand: /klaviyo/events/retry retries one and /klaviyo/events/retry-all retries everything outstanding, which is what an administrator uses after fixing a credential or an outage.

A profile mapping ties a WooCommerce customer to a Klaviyo profile id and records the email, phone, email consent and SMS consent separately, plus a hash of the properties last sent so an unchanged profile is not re-sent.

Separate consent flags matter: consent to email is not consent to SMS, and a module that collapses the two puts the store on the wrong side of that distinction.

Catalogue​

Catalogue items map a WooCommerce product to a Klaviyo item id with a sync hash and a status of pending, synced or failed, plus the error where it failed.

Admin screen​

The Klaviyo tab connects and disconnects the account, shows the connection and an overview, lists Klaviyo lists and the mapped profiles, runs a profile or catalogue sync and shows catalogue status, reads and clears the event log, retries failed events individually or in bulk, edits the settings, and runs diagnostics with a repair action.

REST API endpoints​

All routes are on aiowc/v1, answer with the { success, data, message } envelope, and require an administrator.

MethodPathPurpose
POST/klaviyo/connectConnect the account.
POST/klaviyo/disconnectDisconnect it.
GET/klaviyo/connectionWhether the store is connected.
GET/klaviyo/overviewSummary of events, profiles and catalogue state.
GET/klaviyo/listsThe lists in the connected account.
GET/klaviyo/profilesThe mapped customer profiles.
POST/klaviyo/profiles/syncSync profiles now.
GET/klaviyo/catalog/statusCatalogue sync state.
POST/klaviyo/catalog/syncSync the catalogue now.
GET/klaviyo/events/logsThe event queue and its history.
POST/klaviyo/events/retryRetry one event.
POST/klaviyo/events/retry-allRetry everything outstanding.
POST/klaviyo/events/logs/clearClear the log.
GET / POST/klaviyo/settingsRead and write the settings.
GET/klaviyo/diagnosticsDetected problems.
POST/klaviyo/diagnostics/repairRepair them.

WooCommerce integration​

Beyond the event hooks listed above, the module registers cron_schedules to add the interval its sync jobs run on. It renders nothing on the storefront and changes no WooCommerce behaviour — it observes and reports.

Database schema​

TableHolds
{prefix}aiowc_klaviyo_event_logsThe event queue: type and name, customer email and id, payload, idempotency key, status, attempts, last attempt and next retry, error message and Klaviyo's response.
{prefix}aiowc_klaviyo_profile_mappingsCustomer to Klaviyo profile: profile id, email, phone, email and SMS consent, a properties hash, last sync time.
{prefix}aiowc_klaviyo_catalog_itemsProduct to Klaviyo item: item id, sync hash, status, last sync time and any error.

Background jobs​

HookWork
aiowc_klaviyo_send_eventDrains the pending event queue.
aiowc_klaviyo_retry_failedRe-attempts failed events on their retry schedule.
aiowc_klaviyo_profile_syncSyncs customer profiles.
aiowc_klaviyo_catalog_syncSyncs the product catalogue.
aiowc_klaviyo_log_cleanupPrunes old event rows.

Action hooks for integrators​

HookFired when
aiowc_klaviyo_event_log_created / _updatedAn event is queued or its status changes.
aiowc_track_eventThe module is enabled or disabled.

Entitlement limits​

klaviyo is an on/off grant with no cap on events, profiles or catalogue items. Klaviyo's own account limits apply on their side.

Health check​

The diagnostics route reports the module's own state, and the repair action fixes what it can.

Known gaps​

  • A Klaviyo account and API credentials are required, and none ships with the plugin. Until the store connects one, the module captures no events at all — which is correct behaviour, but means "nothing is happening" is the expected state before connecting.
  • 🔴 Customer personal data leaves the store. Events carry the customer's email and a JSON payload; profiles carry email and phone. That is the entire purpose of the integration, but it is a transfer of identifiable customer data to a third party and must appear in the store's privacy notice, with a lawful basis and — where it applies — a processor agreement with Klaviyo.
  • The module records email and SMS consent on the profile, but that consent has to be collected somewhere; nothing in this module asks the customer for it.
  • The event payload is stored locally in full, so the event log is itself a store of customer data and is pruned only by the cleanup job.
  • No filter is exposed to alter or suppress an event before it is queued, so excluding a particular event type means disabling the hook in code.