OConvert v0.4.0
Conversion optimization for the Orravo stack: A/B test any element, lightweight click heatmaps, and exit-intent triggers. Designed to pair with OMailer, OAds, and OEngage for end-to-end funnel optimization.
What OConvert does
A focused conversion-optimization MVP with three primitives (A/B tests, click heatmaps, exit-intent) wired into the Orravo Suite. Lightweight by design, with all data stored locally in your WordPress database.
[oconvert_test]. Sticky variant assignment per visitor, automatic conversion trackingGetting installed
From WordPress admin
oconvert.zip and click Install Now, then Activate.Manual install (FTP / SFTP)
oconvert.zip.oconvert/ folder to /wp-content/plugins/.wp_oconvert_tests, wp_oconvert_events, wp_oconvert_assignments) and sets the ocv_db_ver option. The visitor cookie ocv_vid is set on the next frontend page load.Your first A/B test
Test two versions of a hero headline using nothing but a shortcode.
[oconvert_test key="hero-headline"]
[oconvert_variant id="a"]Build faster sites today[/oconvert_variant]
[oconvert_variant id="b"]Ship a WordPress site in 7 days[/oconvert_variant]
[/oconvert_test]
wp_oconvert_tests the first time the shortcode renders.draft to running.ocv_vid cookie). Conversions and exposures are recorded automatically.Variant assignment is deterministic (crc32(vid:test_key) % variant_count), so the same visitor always sees the same variant for the lifetime of their cookie (365 days).
Visitor ID & tracking
Every OConvert feature builds on a single primitive: a stable, anonymous visitor identifier issued on first page load.
The ocv_vid cookie
| Property | Value |
|---|---|
| Name | ocv_vid |
| Value | 32-character alphanumeric ID |
| TTL | 365 days |
| Secure | Yes (HTTPS-only) |
| HttpOnly | No (must be readable from JS) |
| SameSite | Lax |
| Set on | First frontend page load (wp_init hook) |
The cookie carries no personally identifiable information. It's a random opaque ID used purely for sticky variant assignment and event correlation.
Frontend config injection
OConvert injects a small JSON config block into <head> on every page:
JS<script id="oconvert-cfg">
window.OCV = {
rest: "https://example.com/wp-json/oconvert/v1",
cookie: "ocv_vid",
tests: [...active tests...],
enabled: { heatmap: true, exit_intent: true },
sample_rate: 0.25,
exit_intent: {...config...}
};
</script>
A/B testing
Two ways to run an A/B test: shortcode wrappers for inline content variants, or DOM patches for changes outside the shortcode boundary.
Shortcode wrappers
Inline variant content. The wrapper picks one variant based on the visitor's sticky assignment.
[oconvert_test key="cta-copy"]
[oconvert_variant id="a"]Get started free[/oconvert_variant]
[oconvert_variant id="b"]Try OConvert today[/oconvert_variant]
[oconvert_variant id="c"]Start your free trial[/oconvert_variant]
[/oconvert_test]
Two or more variants are supported. The number of variants is automatically detected.
DOM patches
For changes outside the shortcode (e.g. test a button color, hide a section, swap an image), define patches on the variant. Patches run client-side after page load.
| Mode | Field used | Behavior |
|---|---|---|
replace | html | Replace the matched element's innerHTML |
text | text | Replace the text content (textContent) |
append | html | insertAdjacentHTML('beforeend', html) |
prepend | html | insertAdjacentHTML('afterbegin', html) |
attr | attr + value | setAttribute(attr, value) on the matched element |
remove | (none) | Detach the matched element from the DOM |
Add patches visually with the click-to-patch editor (open any front-end page as an admin with ?ocv_capture=1&test_key=...&variant=...) or via the REST endpoint POST /test/{key}/variant/{variant}/patches. Patches are stored in wp_oconvert_tests.variants as JSON.
Variant assignment
Deterministic and sticky:
variant_index = crc32(vid + ":" + test_key) % variant_count
The same visitor always sees the same variant. Assignment is also persisted to wp_oconvert_assignments for audit and server-side analysis.
Event types tracked per test
expose: fired when a variant is shown to a visitorconvert: fired when a goal is reached (e.g. CTA click, form submit)
Conversion rate per variant is computed as convert / expose and shown in the test summary endpoint.
Click heatmaps
Lightweight click position recording. Captures only where visitors clicked, binned into a 20×20 grid per page.
What's recorded per click
x_pct,y_pct: click position as % of viewport (resolution-independent)vw,vh: visitor's viewport dimensions at click timetarget: short selector string of clicked element
Aggregation
- Click positions are binned into a 20×20 grid by default (configurable)
- Output shape:
{ "x,y": count, ... } - Most recent 5,000 clicks per page are sampled; older events ignored for performance
- Visualized in the admin under OConvert → Heatmap, page selected by URL
Sample rate
A configurable sample_rate (default 0.25 in the injected config) means only a fraction of visitors send events. Reduces traffic on high-volume sites without losing statistical signal.
Exit-intent triggers
Detect when a visitor is about to leave and surface an HTML payload: newsletter form, discount code, exit survey, anything you want.
Trigger types
| Trigger | Fires when |
|---|---|
mouseleave_top | Cursor moves above the viewport (classic desktop exit-intent) |
scroll_pct | Visitor scrolls past a configured percentage of the page |
time_on_page | Visitor has been on the page for at least min_dwell_ms milliseconds |
tab_blur | Browser tab loses focus (mobile-friendly substitute for mouseleave) |
Multiple triggers can be enabled; the payload fires when any active trigger condition is met.
Configuration
Configured via the admin UI; stored in the oconvert_exit_intent option as JSON:
JSON{
"enabled": true,
"triggers": ["mouseleave_top", "scroll_pct"],
"min_dwell_ms": 4000,
"min_scroll_pct": 60,
"cooldown_days": 7,
"max_per_session": 1,
"payload_html": "<div class='ocv-modal'>...</div>"
}
Frequency caps
cooldown_days: cookie-based; visitor doesn't see the trigger again for N days after dismissmax_per_session: caps how many times the trigger fires per page-view session
Suite integrations
OConvert is designed to feed conversion signals into the rest of the Orravo Suite.
oconvert:exit CustomEvent on every fired trigger. OMailer or OForms popups subscribe to it for on-leave capture.window.OCV.convert(test_key, variant, goal) to attribute a conversion to the active variant.No PHP action hooks like omailer_subscriber_added are required. OConvert keeps the integration surface minimal: one JS CustomEvent for triggers, one helper function for cross-plugin reads, and one public JS conversion API.
Database & REST API
Database tables
| Table | Rows |
|---|---|
wp_oconvert_tests | Test definitions: test_key (UNIQUE), name, status (draft/running), variants (JSON), created_at |
wp_oconvert_events | All tracked events: ev_type, vid, page_url, data (JSON), created_at. Indexed on ev_type, vid, created_at |
wp_oconvert_assignments | Sticky variant assignments: vid, test_key, variant, assigned_at. UNIQUE(vid, test_key) |
Event types
| Type | Data shape |
|---|---|
click | { x_pct, y_pct, vw, vh, target } |
exit | { dwell_ms, action } |
convert | { test_key, variant, goal } |
expose | { test_key, variant } |
REST API endpoints
Namespace: oconvert/v1
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
POST | /event | Public, rate-limited | Ingest an event. Defers DB write to shutdown hook for fast response. |
GET | /heatmap?page_url=… | manage_options | Returns binned 20×20 click grid for a given page |
GET | /test/{key}/summary | manage_options | Returns conversion rate by variant |
POST | /test/{key}/variant/{variant}/patches | manage_options | Add a DOM patch to a variant |
Admin pages
- Overview: active test count, recent events
- A/B Tests: test browser, create/edit, visual patch editor
- Heatmap: page click density visualization
- Exit Intent: rule builder, payload editor, performance stats
- Integrations: status of OMailer / OAds / OEngage hooks
- Settings: feature toggles, sample rate, cooldown defaults
When Orravo Core is active, all six pages register with the Cmd+K command palette.
Filters & hooks
All major behaviors are filterable for custom integrations.
| Filter | Purpose |
|---|---|
oconvert_heatmap_enabled | Globally enable / disable click heatmap recording |
oconvert_heatmap_sample_rate | Override the default sample_rate (0.0–1.0) |
oconvert_exit_intent_enabled | Globally enable / disable exit-intent triggers |
oconvert_exit_intent_config | Modify the exit-intent config before it's injected |
PHP// Disable heatmap on a specific page
add_filter('oconvert_heatmap_enabled', function ($enabled) {
if (is_page('checkout')) return false;
return $enabled;
});
// Lower sample rate to 10% on high-traffic posts
add_filter('oconvert_heatmap_sample_rate', function ($rate) {
if (is_singular('post') && get_post_meta(get_the_ID(), 'high_traffic', true)) {
return 0.10;
}
return $rate;
});
Beta status & roadmap
v0.4.0 is marked public beta: production-usable, with documented gaps.
Shipped in 0.4
- Shortcode-based A/B tests with sticky variant assignment
- DOM patch system (6 patch modes)
- Click heatmap recording with 20×20 bin aggregation
- Exit-intent (4 trigger types) with frequency caps
- Suite integration hooks (OMailer / OAds / OEngage)
- REST API with rate-limited public ingest endpoint
- Six-tab admin UI
Planned for 1.0
- Goal & funnel reporting: multi-step conversion paths with drop-off visualization
- Multivariate experiments: test combinations of multiple changes simultaneously
Frequently asked questions
ocv_vid cookie carries no PII; it's a random 32-char identifier. Whether it requires consent under GDPR depends on your jurisdiction's interpretation of "strictly necessary" cookies. If your consent banner gates analytics cookies, gate OConvert behind it via the oconvert_heatmap_enabled filter.shutdown hook, so the FPM worker is released before the row is written. Response times stay under 50ms even under load.ocv_vid cookie, which is per-browser. A visitor on mobile and desktop will get separate variant assignments. There's no cross-device identity stitching in v0.4.[oconvert_test] shortcodes will render the raw shortcode text (default WordPress behavior). Reactivating restores all tests and data; nothing is dropped on deactivation. Only deleting the plugin drops the wp_oconvert_* tables.sample_rate (default 0.25) means only a fraction of visitors send click events. Per-page, only the most recent 5,000 clicks contribute to the binned visualization. Older clicks remain in wp_oconvert_events for raw analysis but don't load the visualization.key attribute. Variant assignments are independent per test, so tests do not bias one another.cooldown_days (cookie-based; visitor doesn't see it again for N days after dismiss) and max_per_session (caps fires per page-view session). Set both to keep the experience non-annoying.Got a question about OConvert?
Reach out directly. Kenneth replies within 24 hours.

