CleverTap
Connect CleverTap to JustAI to run AI-optimized copy experiments in your existing campaigns. CleverTap fetches the best content variant for each recipient at send time through Linked Content, and JustAI learns from the opens, clicks, and conversions you send back.
How it works
Section titled “How it works”- You create a Linked Content API in CleverTap that points to JustAI’s content endpoint.
- At send time, CleverTap calls JustAI for each recipient and exposes the returned copy (subject, preheader, HTML body, and a copy ID) to your Email, Push, SMS, and In-app messages as
Linked.JustAI.*Liquid variables. (CleverTap User Docs) - You split each campaign with CleverTap’s A/B & Multivariate Testing: the control group keeps your current copy, and the treatment group uses the JustAI variables. (CleverTap User Docs)
- CleverTap streams or exports campaign events (sends, opens, clicks, and more) back to JustAI via webhooks or S3 exports. (CleverTap User Docs)
- JustAI joins those events with its record of which copy each recipient received, and serves better-performing copy over time.
Before you start
Section titled “Before you start”- Your JustAI org slug — usually your company name in lowercase (ask us if you’re not sure).
- A JustAI API key (JustAI Console → Settings → API Keys).
- The template ID (
template_id) of the JustAI template you want to serve. - Access to CleverTap Settings (to add a Linked Content API) and to campaign creation.
Connect CleverTap to JustAI
Section titled “Connect CleverTap to JustAI”This is one-time setup: point CleverTap at JustAI’s content endpoint, then set up the flow of campaign events back to JustAI.
Step 1 — Create a Linked Content API
Section titled “Step 1 — Create a Linked Content API”-
In CleverTap, go to Settings → Setup → Linked Content → + Linked Content.
-
Set the API Name to
JustAI. -
Set the Endpoint (GET) — recommended for Linked Content:
https://worker.justwords.ai/api/generate/<org_slug>?template_id=<template_id> -
Auth: add your JustAI API key as
X-Api-Key(the CleverTap UI supports adding an access key/params on the API). -
Add the query params to include:
user_id={{Profile.Identity}}- Any attributes you want JustAI to personalize on — see Personalization.
-
Test the API in the Linked Content UI and use Auto-fill objects so CleverTap exposes
Linked.JustAI.*labels in Liquid. The response is parsed as JSON and exposed to Liquid. (CleverTap User Docs)
JustAI returns copy.id and copy.vars.{…} fields such as subject, preheader, and body, which you access in CleverTap as Linked.JustAI.copy.*:
{ "copy": { "id": "uuid", "vars": { "subject": "...", "preheader": "...", "body": "<html>…</html>" } }}Step 2 — Send campaign events to JustAI
Section titled “Step 2 — Send campaign events to JustAI”Send engagement events for both control and treatment back to JustAI so it can measure which copy wins. Pick any one option (or combine them).
Option A — Custom events webhook (near-real-time)
Section titled “Option A — Custom events webhook (near-real-time)”After JustAI confirms the payload mapping for your organization, create a Webhook campaign in CleverTap and post events to the generic JustAI events endpoint:
- CleverTap → Campaigns → +Campaign → Webhooks → Go To Editor.
- Destination:
https://worker.justwords.ai/api/webhook/events/<org_slug> - Auth header:
X-Api-Key: <JUSTAI_API_KEY> - Send only the event types and fields included in your validated mapping. The following payload is illustrative; do not assume raw CleverTap events are accepted without that mapping:
{ "platform": "clevertap", "channel": "email", "event": "{{EventName}}", "campaign_id": "{{Campaign.campaignId}}", "variant_hint": "{{wzrk_pivot}}", "user_id": "{{Profile.Identity}}", "email": "{{Profile.Email}}", "timestamp": "{{now}}", "justai_copy_id": "{{ Linked.JustAI.copy.id }}"}You define the body in the Webhook Editor, and you can include identity, profile, and event properties. (CleverTap User Docs)
Option B — Post Action Webhooks (Push campaigns)
Section titled “Option B — Post Action Webhooks (Push campaigns)”If you’re testing Push, enable Post Action Webhooks on the push campaign. CleverTap will POST message-level data (including the notification payload and keys such as wzrk_pivot for the A/B variant) after delivery. Point it to your JustAI endpoint. (CleverTap User Docs)
Option C — AWS S3 exports (batch)
Section titled “Option C — AWS S3 exports (batch)”- Configure Settings → Partners → Exports to Amazon S3 and write a daily scrubbed dataset under a JustAI-provisioned prefix (e.g.,
s3://justwords-metrics-ingest/<org>). (CleverTap User Docs) - Include
event_timestamp,event_name,campaign_id, and (if available) linkage such as message/template IDs. JustAI reads these files for attribution. The suggested unified schema and S3 layout are the same across JustAI integrations.
How JustAI uses these events: JustAI joins CleverTap engagement (by user, campaign, and timestamp) with its own serve logs — the record of which copy each recipient received, including copy_id — to compute per-variant lift across control and treatment. Include justai_copy_id when feasible to make the joins trivial.
Set up a campaign
Section titled “Set up a campaign”Use JustAI content in your message
Section titled “Use JustAI content in your message”CleverTap supports Liquid tags across channels (Email, Push, SMS, Webhooks, WhatsApp, Native Display). In the campaign’s What section, map your Linked Content API and then reference values with Liquid: (CleverTap User Docs)
- Subject (Email “Subject” field):
{{ Linked.JustAI.copy.vars.subject | default:"" }} - Preheader (Email “Preheader” field):
{{ Linked.JustAI.copy.vars.preheader | default:"" }} - HTML body (drag-and-drop block → “Customize with Liquid tags”, or source HTML):
{{ Linked.JustAI.copy.vars.body }}<!-- JUSTAI_COPY_ID: {{ Linked.JustAI.copy.id }} -->Liquid + Linked Content are available in the drag-and-drop editor too. (CleverTap User Docs)
Add a fallback (recommended)
Section titled “Add a fallback (recommended)”Use CleverTap’s system labels to gate content if the API is slow or fails:
{% if Linked.JustAI.http_status_code == 200 %} {{ Linked.JustAI.copy.vars.body }}{% else %} {{ Profile.fallback_html | default:"" }}{% endif %}Available system labels include http_status_code, JSON, raw, and more. (CleverTap User Docs)
Split control and treatment
Section titled “Split control and treatment”Run each campaign as a split test: the control group keeps your current copy as the baseline, and the treatment group receives JustAI copy.
Option A — Campaign A/B test (most common)
Section titled “Option A — Campaign A/B test (most common)”- In your campaign, add A/B & Multivariate Testing.
- Variant A (Control): your current static content.
- Variant B (Treatment): the same creative, but replace subject/preheader/body with the
Linked.JustAILiquid tags above. - Run a 50/50 test (or your preferred split). CleverTap auto-determines winners by channel-appropriate metrics (clicks; for email, views/opens). (CleverTap User Docs)
Option B — Journeys
Section titled “Option B — Journeys”- In a Journey, branch traffic (IntelliNODE or an A/B branch) and place the Linked Content Liquid on the treatment path. (CleverTap User Docs)
Personalization
Section titled “Personalization”Pass recipient attributes as query params on the Linked Content call so JustAI can tailor copy to each person. Use Liquid default filters so a missing profile field never breaks the call.
- Always include the recipient’s identity:
user_id={{Profile.Identity}} - Examples of attributes to personalize on:
first_name={{Profile.name | default:"there"}}gender={{Profile.gender | default:"unknown"}}cohort={{Profile.segment | default:"default"}}
Advanced
Section titled “Advanced”Ready-to-copy snippets
Section titled “Ready-to-copy snippets”Linked Content URL (GET)
https://worker.justwords.ai/api/generate/<org_slug>?template_id=<template_id>&user_id={{Profile.Identity}}&first={{Profile.name | default:"there"}}&gender={{Profile.gender | default:"unknown"}}Liquid variables resolve per recipient; the response appears under Linked.JustAI.*. (CleverTap User Docs)
Email subject / preheader / body
{{ Linked.JustAI.copy.vars.subject | default:"" }}{{ Linked.JustAI.copy.vars.preheader | default:"" }}{{ Linked.JustAI.copy.vars.body }}<!-- JUSTAI_COPY_ID: {{ Linked.JustAI.copy.id }} -->Check your setup with curl
Section titled “Check your setup with curl”Run this from a terminal to confirm your template and org are wired up. It returns the same response fields you’ll read in Linked Content:
export JUSTAI_API_KEY=...curl -X POST "https://worker.justwords.ai/api/generate/<org_slug>" \ -H "X-Api-Key: $JUSTAI_API_KEY" -H "Content-Type: application/json" \ -d '{"template_id":"sample","attrs":{"role":"school"}}'You can also call the endpoint with GET and template_id in the query string (as the Linked Content API does); the response shape is the same.
Example event payloads
Section titled “Example event payloads”If you stream additional custom events to JustAI (for example, conversions such as purchases), a minimal payload looks like:
{ "event_timestamp": 1700000000, "user_id": "abc123", "event_name": "purchase"}If you prefer batch, write to the shared S3 prefix in parquet and partition by time; include campaign_id/template_id where possible.
Troubleshooting
Section titled “Troubleshooting”- Content is missing or the fallback always shows — Linked Content waits ~5s and does not retry failed calls. Always include the fallback pattern from Add a fallback. (CleverTap User Docs)
- Duplicate or delayed webhook events — CleverTap webhooks use a 5s timeout with 2 retries, so retried deliveries can arrive more than once; plan idempotency on the JustAI side. (CleverTap User Docs)
- A/B results are hard to read — You can test up to three variants; for email, winners often use opens/views, and for push/SMS, clicks. Keep a 50/50 split for clean readouts, or let CleverTap auto-select winners. (CleverTap User Docs)
- Clicks can’t be tied to a specific variant — Add
JUSTAI_COPY_IDas a hidden HTML comment or URL param so any click carries the servedcopy_id. JustAI also supports joining by user/campaign/timestamp if you prefer batch exports.