CleverTap
What you get
Section titled “What you get”- Send‑time content: CleverTap calls JustAI via Linked Content; you drop variables (subject, preheader, HTML body, copy_id) into Email / Push / SMS / In‑app using Liquid. (CleverTap User Docs)
- Control vs Treatment in CleverTap: Use A/B & Multivariate Testing to split traffic; put Linked Content on the treatment. (CleverTap User Docs)
- Closed‑loop learning: Stream or export campaign events (sends/opens/clicks, etc.) back to JustAI via Webhooks / Post Action Webhooks and/or S3 exports. (CleverTap User Docs)
Prereqs
Section titled “Prereqs”- JustAI API key (Console → Settings → API Keys).
- Your org slug in JustAI and the template_id you want to serve.
JustAI Generate API (shape & examples): returns copy.id and copy.vars.{…} such as subject, preheader, body.
You can also call JAI via a GET endpoint with template_id in the query string (as used in MoEngage); the response shape is the same.
1) Fetch send‑time copy in CleverTap (Linked Content)
Section titled “1) Fetch send‑time copy in CleverTap (Linked Content)”A. Create a Linked Content API
Section titled “A. Create a Linked Content API”-
CleverTap → Settings → Setup → Linked Content → + Linked Content.
- API Name:
JustAI
- API Name:
-
Endpoint (GET) (recommended for Linked Content):
https://worker.justwords.ai/api/generate/<org_slug>?template_id=<template_id>- Auth: Add your
X-Api-Key(CleverTap UI supports adding an access key/params on the API). - Params to include (as query params):
user_id={{Profile.Identity}}- Any attributes you want JAI to personalize on (examples):
first_name={{Profile.name | default:"there"}}gender={{Profile.gender | default:"unknown"}}cohort={{Profile.segment | default:"default"}}
- Auth: Add your
-
Test the API in the Linked Content UI and Auto‑fill objects so CleverTap exposes
Linked.JustAI.*labels in Liquid. (Response is parsed as JSON and exposed to Liquid.) (CleverTap User Docs)
Notes & limits: Linked Content fetches run at send‑time, the response is always JSON, and CleverTap will wait up to ~5s and does not retry failed calls. Plan a fallback. (CleverTap User Docs)
B. Use it in campaigns (Email / Push / SMS / Webhooks / WhatsApp / Native Display)
Section titled “B. Use it in campaigns (Email / Push / SMS / Webhooks / WhatsApp / Native Display)”CleverTap supports Liquid tags across channels. In the campaign’s What section, map your 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 }}<!-- JAI_COPY_ID: {{ Linked.JustAI.copy.id }} -->(Liquid + Linked Content are available in the drag‑and‑drop editor too.) (CleverTap User Docs)
C. Robust fallback (recommended)
Section titled “C. Robust 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, etc.) (CleverTap User Docs)
Reference (JustAI response shape)
{ "copy": { "id": "uuid", "vars": { "subject": "...", "preheader": "...", "body": "<html>…</html>" } }}(What JustAI returns; you’ll access it in CleverTap as Linked.JustAI.copy.*.)
2) Build Control vs Treatment in CleverTap
Section titled “2) Build Control vs Treatment in CleverTap”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): same creative, but replace subject/preheader/body with the Linked.JustAI Liquid 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 A/B branch) and place the Linked Content Liquid on the treatment path. (CleverTap User Docs)
Tip: Add the hidden JAI_COPY_ID comment shown above or append a link param (e.g., utm_jai={{ Linked.JustAI.copy.id }}) so you can attribute clicks to the served variant.
3) Send CleverTap engagement back to JustAI (control & treatment)
Section titled “3) Send CleverTap engagement back to JustAI (control & treatment)”Pick any one (or combine):
A) Webhooks as a channel (broad, near‑real‑time)
Section titled “A) Webhooks as a channel (broad, near‑real‑time)”Create a Webhook campaign in CleverTap and post events to your JAI events endpoint:
- CleverTap → Campaigns → +Campaign → Webhooks → Go To Editor.
- Destination:
https://worker.justwords.ai/api/webhook/clevertap/<org_slug> - Auth header:
X-Api-Key: <JAI_API_KEY> - Send payloads for sends/opens/clicks/unsubs with the keys below (you can include user/profile fields directly from the editor):
{ "platform": "clevertap", "channel": "email", "event": "{{EventName}}", "campaign_id": "{{Campaign.campaignId}}", "variant_hint": "{{wzrk_pivot}}", "user_id": "{{Profile.Identity}}", "email": "{{Profile.Email}}", "timestamp": "{{now}}", "jai_copy_id": "{{ Linked.JustAI.copy.id }}"}(You define the body in Webhook Editor, and you can include identity/profile/event properties.) (CleverTap User Docs)
B) Post Action Webhooks (Push campaigns)
Section titled “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 notification payload and keys such as wzrk_pivot for A/B variant) after delivery. Point it to your JAI endpoint. (CleverTap User Docs)
C) AWS S3 Exports (batch)
Section titled “C) AWS S3 Exports (batch)”- Configure Settings → Partners → Exports to Amazon S3 and write a daily scrubbed dataset under a JAI‑provisioned prefix (e.g.,
s3://justai-metrics-ingest/<org>). - Include
event_timestamp,event_name,campaign_id, and (if available) linkage like message/template IDs. JAI ingests these for attribution. (CleverTap User Docs)- JAI’s suggested unified schema & S3 pattern are the same ones you’ve used elsewhere.
How JAI uses it: JAI joins CleverTap engagement (by user/campaign/timestamp) with JAI serve logs (which include copy_id) to compute per‑variant lift — across control & treatment branches. Include jai_copy_id when feasible to make joins trivial.
4) Ready‑to‑copy snippets
Section titled “4) 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; 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 }}<!-- JAI_COPY_ID: {{ Linked.JustAI.copy.id }} -->JAI Generate API (curl sanity check)
export JAI_API_KEY=...curl -X POST "https://worker.justwords.ai/api/generate/<org_slug>" \ -H "X-Api-Key: $JAI_API_KEY" -H "Content-Type: application/json" \ -d '{"template_id":"sample","attrs":{"role":"school"}}'(Confirms your template and org are wired; same response fields you’ll read in Linked Content.)
Gotchas & best practices
Section titled “Gotchas & best practices”- Linked Content timeouts & retries: CleverTap waits ~5s, no retries — include a fallback. (CleverTap User Docs)
- Webhooks timeouts & retries: 5s timeout with 2 retries. Plan idempotency on JAI’s side. (CleverTap User Docs)
- A/B inside CleverTap: You can test up to three variants; for email, winners often use opens/views; for push/SMS, clicks. Keep 50/50 for clean readouts or let CleverTap auto‑select winners. (CleverTap User Docs)
- Attribution: Add
JAI_COPY_IDas a hidden HTML comment or URL param so any click carries the servedcopy_id. JAI also supports joining by user/campaign/timestamp if you prefer batch exports.
Appendix — What “good” payloads look like (JAI ingest)
Section titled “Appendix — What “good” payloads look like (JAI ingest)”Streaming custom events (generic)
{ "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.)
If you’d like, I can turn this into a pre-filled Linked Content JSON mapping and a webhook payload you can paste into your CleverTap workspace (with your org/template IDs and the Liquid fields you already use).