@apex-inc/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +165 -0
- package/dist/esm/index.js +180 -0
- package/dist/esm/management.js +152 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +224 -0
- package/dist/index.js.map +1 -0
- package/dist/management.d.ts +50 -0
- package/dist/management.d.ts.map +1 -0
- package/dist/management.js +156 -0
- package/dist/management.js.map +1 -0
- package/package.json +32 -0
- package/skills/apex-communications/SKILL.md +135 -0
- package/skills/apex-experimentation/SKILL.md +70 -0
- package/skills/apex-growth-tracking/SKILL.md +41 -0
- package/skills/apex-integration-cookbook/SKILL.md +137 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createManagementClient = void 0;
|
|
37
|
+
exports.init = init;
|
|
38
|
+
exports.track = track;
|
|
39
|
+
exports.identify = identify;
|
|
40
|
+
exports.trackForm = trackForm;
|
|
41
|
+
exports.flush = flush;
|
|
42
|
+
exports.shutdown = shutdown;
|
|
43
|
+
const isBrowser = typeof window !== "undefined";
|
|
44
|
+
const DEFAULT_API_URL = isBrowser ? window.location.origin : "http://localhost:3000";
|
|
45
|
+
let config = null;
|
|
46
|
+
let queue = [];
|
|
47
|
+
let flushTimer = null;
|
|
48
|
+
let userId = null;
|
|
49
|
+
function log(...args) {
|
|
50
|
+
if (config?.debug)
|
|
51
|
+
console.log("[apex-sdk]", ...args);
|
|
52
|
+
}
|
|
53
|
+
async function sendBatch(events) {
|
|
54
|
+
if (!config || events.length === 0)
|
|
55
|
+
return;
|
|
56
|
+
const apiUrl = config.apiUrl ?? DEFAULT_API_URL;
|
|
57
|
+
const url = `${apiUrl.replace(/\/$/, "")}/api/events`;
|
|
58
|
+
const body = JSON.stringify({
|
|
59
|
+
projectKey: config.projectKey,
|
|
60
|
+
userId,
|
|
61
|
+
events,
|
|
62
|
+
});
|
|
63
|
+
try {
|
|
64
|
+
const fetchFn = typeof fetch !== "undefined" ? fetch : await loadNodeFetch();
|
|
65
|
+
const res = await fetchFn(url, {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers: { "Content-Type": "application/json" },
|
|
68
|
+
body,
|
|
69
|
+
});
|
|
70
|
+
log(`Flushed ${events.length} events — ${res.status}`);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
log("Flush failed:", err);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function loadNodeFetch() {
|
|
77
|
+
// Fallback for older Node.js environments without global fetch
|
|
78
|
+
try {
|
|
79
|
+
const mod = await Promise.resolve(`${"node-fetch"}`).then(s => __importStar(require(s)));
|
|
80
|
+
return mod.default;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
throw new Error("apex-sdk: fetch is not available. Use Node.js 18+ or install node-fetch.");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function startFlushTimer() {
|
|
87
|
+
if (flushTimer)
|
|
88
|
+
return;
|
|
89
|
+
const interval = config?.flushInterval ?? 5000;
|
|
90
|
+
flushTimer = setInterval(() => flush(), interval);
|
|
91
|
+
if (isBrowser) {
|
|
92
|
+
window.addEventListener("beforeunload", () => flush());
|
|
93
|
+
document.addEventListener("visibilitychange", () => {
|
|
94
|
+
if (document.visibilityState === "hidden")
|
|
95
|
+
flush();
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function enqueue(event) {
|
|
100
|
+
queue.push(event);
|
|
101
|
+
const flushAt = config?.flushAt ?? 20;
|
|
102
|
+
if (queue.length >= flushAt)
|
|
103
|
+
flush();
|
|
104
|
+
}
|
|
105
|
+
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
106
|
+
/**
|
|
107
|
+
* Initialize the Apex SDK. Must be called before track() or identify().
|
|
108
|
+
*/
|
|
109
|
+
function init(options) {
|
|
110
|
+
config = options;
|
|
111
|
+
queue = [];
|
|
112
|
+
log("Initialized with project:", options.projectKey);
|
|
113
|
+
startFlushTimer();
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Track a custom event.
|
|
117
|
+
*/
|
|
118
|
+
function track(event, properties) {
|
|
119
|
+
if (!config) {
|
|
120
|
+
console.warn("[apex-sdk] Call init() before track()");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
log("Track:", event, properties);
|
|
124
|
+
enqueue({
|
|
125
|
+
type: "track",
|
|
126
|
+
payload: { event, properties, timestamp: new Date().toISOString() },
|
|
127
|
+
timestamp: new Date().toISOString(),
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Identify a user with traits (email, name, plan, etc.).
|
|
132
|
+
* Also performs identity stitching if the userId looks like an email.
|
|
133
|
+
*
|
|
134
|
+
* Pass `traits.visitorId` (the browser's `apex_vid` cookie value) to stitch
|
|
135
|
+
* server-side identify calls to the real browser session. Without it, the SDK
|
|
136
|
+
* creates a synthetic visitor ID that is disconnected from marketing touchpoints.
|
|
137
|
+
*
|
|
138
|
+
* PLG integration pattern:
|
|
139
|
+
* apex.identify('user@example.com', { visitorId: req.cookies.apex_vid })
|
|
140
|
+
*/
|
|
141
|
+
function identify(userId_, traits) {
|
|
142
|
+
if (!config) {
|
|
143
|
+
console.warn("[apex-sdk] Call init() before identify()");
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
userId = userId_;
|
|
147
|
+
log("Identify:", userId, traits);
|
|
148
|
+
enqueue({
|
|
149
|
+
type: "identify",
|
|
150
|
+
payload: { userId: userId_, traits },
|
|
151
|
+
timestamp: new Date().toISOString(),
|
|
152
|
+
});
|
|
153
|
+
const email = userId_.includes("@") ? userId_ : traits?.email;
|
|
154
|
+
if (email) {
|
|
155
|
+
const browserVisitorId = traits?.visitorId;
|
|
156
|
+
stitchIdentity(email, browserVisitorId, traits);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function stitchIdentity(email, browserVisitorId, metadata) {
|
|
160
|
+
if (!config)
|
|
161
|
+
return;
|
|
162
|
+
const apiUrl = config.apiUrl ?? DEFAULT_API_URL;
|
|
163
|
+
const url = `${apiUrl.replace(/\/$/, "")}/api/identity/stitch`;
|
|
164
|
+
const effectiveVisitorId = browserVisitorId || `sdk-${config.projectKey}-${email}`;
|
|
165
|
+
try {
|
|
166
|
+
const fetchFn = typeof fetch !== "undefined" ? fetch : await loadNodeFetch();
|
|
167
|
+
await fetchFn(url, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers: { "Content-Type": "application/json" },
|
|
170
|
+
body: JSON.stringify({
|
|
171
|
+
visitorId: effectiveVisitorId,
|
|
172
|
+
email,
|
|
173
|
+
projectKey: config.projectKey,
|
|
174
|
+
metadata: metadata ?? {},
|
|
175
|
+
}),
|
|
176
|
+
});
|
|
177
|
+
log("Identity stitched for:", email, "visitor:", effectiveVisitorId);
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
log("Identity stitch failed:", err);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Track a form submission event with the email for identity stitching.
|
|
185
|
+
*/
|
|
186
|
+
function trackForm(formData) {
|
|
187
|
+
if (!config) {
|
|
188
|
+
console.warn("[apex-sdk] Call init() before trackForm()");
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const { email, formId, action, fields } = formData;
|
|
192
|
+
log("TrackForm:", email, formId);
|
|
193
|
+
track("form_submit", {
|
|
194
|
+
formId,
|
|
195
|
+
formAction: action,
|
|
196
|
+
email,
|
|
197
|
+
...(fields ?? {}),
|
|
198
|
+
});
|
|
199
|
+
identify(email, { source: "form", formId });
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Immediately flush all queued events to the server.
|
|
203
|
+
*/
|
|
204
|
+
function flush() {
|
|
205
|
+
if (queue.length === 0)
|
|
206
|
+
return;
|
|
207
|
+
const batch = queue.splice(0, queue.length);
|
|
208
|
+
sendBatch(batch);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Shut down the SDK — flush remaining events and stop the timer.
|
|
212
|
+
*/
|
|
213
|
+
function shutdown() {
|
|
214
|
+
flush();
|
|
215
|
+
if (flushTimer) {
|
|
216
|
+
clearInterval(flushTimer);
|
|
217
|
+
flushTimer = null;
|
|
218
|
+
}
|
|
219
|
+
config = null;
|
|
220
|
+
log("Shut down");
|
|
221
|
+
}
|
|
222
|
+
var management_1 = require("./management");
|
|
223
|
+
Object.defineProperty(exports, "createManagementClient", { enumerable: true, get: function () { return management_1.createManagementClient; } });
|
|
224
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic access to Apex APIs using an API key (same as MCP server).
|
|
3
|
+
* Intended for Node.js backends; sends x-api-key and x-apex-project on each request.
|
|
4
|
+
*/
|
|
5
|
+
export interface ManagementConfig {
|
|
6
|
+
projectKey: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
/** Base URL of the Apex app (no trailing slash), e.g. https://app.example.com */
|
|
9
|
+
apiUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AssignVariantResult {
|
|
12
|
+
variant: string;
|
|
13
|
+
experimentId: string;
|
|
14
|
+
visitorId?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create a minimal management client for server-side experiment reads and variant assignment.
|
|
18
|
+
* Assignment uses Cookie apex_vid + apex_project so GET /api/experiments/[id]/assign resolves consistently.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createManagementClient(cfg: ManagementConfig): {
|
|
21
|
+
listExperiments(): Promise<unknown[]>;
|
|
22
|
+
assignVariant(experimentId: string, visitorId: string): Promise<AssignVariantResult>;
|
|
23
|
+
recommendCommunications(): Promise<unknown>;
|
|
24
|
+
generateCommunications(catalogEntryIds: string[]): Promise<unknown[]>;
|
|
25
|
+
listCommunications(): Promise<unknown[]>;
|
|
26
|
+
getCommunication(id: string): Promise<unknown>;
|
|
27
|
+
updateCommunication(id: string, updates: Record<string, unknown>): Promise<unknown>;
|
|
28
|
+
deleteCommunication(id: string): Promise<void>;
|
|
29
|
+
previewCommunication(id: string): Promise<{
|
|
30
|
+
subject: string;
|
|
31
|
+
html: string;
|
|
32
|
+
}>;
|
|
33
|
+
sendTestCommunication(id: string): Promise<void>;
|
|
34
|
+
triggerCommunication(id: string, opts: {
|
|
35
|
+
recipientEmail: string;
|
|
36
|
+
mergeData?: Record<string, string>;
|
|
37
|
+
}): Promise<void>;
|
|
38
|
+
listCommExperiments(): Promise<unknown[]>;
|
|
39
|
+
createCommExperiment(params: {
|
|
40
|
+
communicationId: string;
|
|
41
|
+
splitLevel: string;
|
|
42
|
+
funnelGoal: string;
|
|
43
|
+
variants: unknown[];
|
|
44
|
+
}): Promise<unknown>;
|
|
45
|
+
startCommExperiment(id: string): Promise<void>;
|
|
46
|
+
promoteCommExperimentWinner(id: string): Promise<void>;
|
|
47
|
+
getEventTaxonomy(): Promise<unknown[]>;
|
|
48
|
+
getEventIntegrationStatus(): Promise<unknown[]>;
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=management.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"management.d.ts","sourceRoot":"","sources":["../src/management.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAcD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,gBAAgB;uBAK/B,OAAO,CAAC,OAAO,EAAE,CAAC;gCAST,MAAM,aAAa,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;+BAoBzD,OAAO,CAAC,OAAO,CAAC;4CAMH,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;0BAQ/C,OAAO,CAAC,OAAO,EAAE,CAAC;yBAMnB,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;4BAMtB,MAAM,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;4BAQ3D,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;6BAOrB,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;8BAQlD,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;6BAOvB,MAAM,QAAQ;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;2BAS9F,OAAO,CAAC,OAAO,EAAE,CAAC;iCAMZ;QACjC,eAAe,EAAE,MAAM,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,OAAO,EAAE,CAAC;KACrB,GAAG,OAAO,CAAC,OAAO,CAAC;4BAQU,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;oCAOd,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;wBASlC,OAAO,CAAC,OAAO,EAAE,CAAC;iCAMT,OAAO,CAAC,OAAO,EAAE,CAAC;EAMxD"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Programmatic access to Apex APIs using an API key (same as MCP server).
|
|
4
|
+
* Intended for Node.js backends; sends x-api-key and x-apex-project on each request.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.createManagementClient = createManagementClient;
|
|
8
|
+
function baseUrl(cfg) {
|
|
9
|
+
return (cfg.apiUrl ?? "http://localhost:3000").replace(/\/$/, "");
|
|
10
|
+
}
|
|
11
|
+
function keyHeaders(cfg) {
|
|
12
|
+
return {
|
|
13
|
+
"Content-Type": "application/json",
|
|
14
|
+
"x-api-key": cfg.apiKey,
|
|
15
|
+
"x-apex-project": cfg.projectKey,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a minimal management client for server-side experiment reads and variant assignment.
|
|
20
|
+
* Assignment uses Cookie apex_vid + apex_project so GET /api/experiments/[id]/assign resolves consistently.
|
|
21
|
+
*/
|
|
22
|
+
function createManagementClient(cfg) {
|
|
23
|
+
const root = baseUrl(cfg);
|
|
24
|
+
const headers = keyHeaders(cfg);
|
|
25
|
+
return {
|
|
26
|
+
async listExperiments() {
|
|
27
|
+
const res = await fetch(`${root}/api/experiments`, { headers });
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
const text = await res.text().catch(() => "");
|
|
30
|
+
throw new Error(`Apex listExperiments failed (${res.status}): ${text}`);
|
|
31
|
+
}
|
|
32
|
+
return res.json();
|
|
33
|
+
},
|
|
34
|
+
async assignVariant(experimentId, visitorId) {
|
|
35
|
+
const cookie = [
|
|
36
|
+
`apex_vid=${encodeURIComponent(visitorId)}`,
|
|
37
|
+
`apex_project=${encodeURIComponent(cfg.projectKey)}`,
|
|
38
|
+
].join("; ");
|
|
39
|
+
const res = await fetch(`${root}/api/experiments/${encodeURIComponent(experimentId)}/assign`, {
|
|
40
|
+
headers: { ...headers, Cookie: cookie },
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
const text = await res.text().catch(() => "");
|
|
44
|
+
throw new Error(`Apex assignVariant failed (${res.status}): ${text}`);
|
|
45
|
+
}
|
|
46
|
+
return res.json();
|
|
47
|
+
},
|
|
48
|
+
// ─── Communications ───────────────────────────────────────────────
|
|
49
|
+
async recommendCommunications() {
|
|
50
|
+
const res = await fetch(`${root}/api/communications/recommend`, { method: "POST", headers });
|
|
51
|
+
if (!res.ok)
|
|
52
|
+
throw new Error(`Apex recommendCommunications failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
53
|
+
return res.json();
|
|
54
|
+
},
|
|
55
|
+
async generateCommunications(catalogEntryIds) {
|
|
56
|
+
const res = await fetch(`${root}/api/communications/generate`, {
|
|
57
|
+
method: "POST", headers, body: JSON.stringify({ catalogEntryIds }),
|
|
58
|
+
});
|
|
59
|
+
if (!res.ok)
|
|
60
|
+
throw new Error(`Apex generateCommunications failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
61
|
+
return res.json();
|
|
62
|
+
},
|
|
63
|
+
async listCommunications() {
|
|
64
|
+
const res = await fetch(`${root}/api/communications`, { headers });
|
|
65
|
+
if (!res.ok)
|
|
66
|
+
throw new Error(`Apex listCommunications failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
67
|
+
return res.json();
|
|
68
|
+
},
|
|
69
|
+
async getCommunication(id) {
|
|
70
|
+
const res = await fetch(`${root}/api/communications/${encodeURIComponent(id)}`, { headers });
|
|
71
|
+
if (!res.ok)
|
|
72
|
+
throw new Error(`Apex getCommunication failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
73
|
+
return res.json();
|
|
74
|
+
},
|
|
75
|
+
async updateCommunication(id, updates) {
|
|
76
|
+
const res = await fetch(`${root}/api/communications/${encodeURIComponent(id)}`, {
|
|
77
|
+
method: "PATCH", headers, body: JSON.stringify(updates),
|
|
78
|
+
});
|
|
79
|
+
if (!res.ok)
|
|
80
|
+
throw new Error(`Apex updateCommunication failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
81
|
+
return res.json();
|
|
82
|
+
},
|
|
83
|
+
async deleteCommunication(id) {
|
|
84
|
+
const res = await fetch(`${root}/api/communications/${encodeURIComponent(id)}`, {
|
|
85
|
+
method: "DELETE", headers,
|
|
86
|
+
});
|
|
87
|
+
if (!res.ok)
|
|
88
|
+
throw new Error(`Apex deleteCommunication failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
89
|
+
},
|
|
90
|
+
async previewCommunication(id) {
|
|
91
|
+
const res = await fetch(`${root}/api/communications/${encodeURIComponent(id)}/preview`, {
|
|
92
|
+
method: "POST", headers,
|
|
93
|
+
});
|
|
94
|
+
if (!res.ok)
|
|
95
|
+
throw new Error(`Apex previewCommunication failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
96
|
+
return res.json();
|
|
97
|
+
},
|
|
98
|
+
async sendTestCommunication(id) {
|
|
99
|
+
const res = await fetch(`${root}/api/communications/${encodeURIComponent(id)}/test`, {
|
|
100
|
+
method: "POST", headers,
|
|
101
|
+
});
|
|
102
|
+
if (!res.ok)
|
|
103
|
+
throw new Error(`Apex sendTestCommunication failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
104
|
+
},
|
|
105
|
+
async triggerCommunication(id, opts) {
|
|
106
|
+
const res = await fetch(`${root}/api/communications/${encodeURIComponent(id)}/send`, {
|
|
107
|
+
method: "POST", headers, body: JSON.stringify(opts),
|
|
108
|
+
});
|
|
109
|
+
if (!res.ok)
|
|
110
|
+
throw new Error(`Apex triggerCommunication failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
111
|
+
},
|
|
112
|
+
// ─── Communication Experiments ────────────────────────────────────
|
|
113
|
+
async listCommExperiments() {
|
|
114
|
+
const res = await fetch(`${root}/api/communications/experiments`, { headers });
|
|
115
|
+
if (!res.ok)
|
|
116
|
+
throw new Error(`Apex listCommExperiments failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
117
|
+
return res.json();
|
|
118
|
+
},
|
|
119
|
+
async createCommExperiment(params) {
|
|
120
|
+
const res = await fetch(`${root}/api/communications/experiments`, {
|
|
121
|
+
method: "POST", headers, body: JSON.stringify(params),
|
|
122
|
+
});
|
|
123
|
+
if (!res.ok)
|
|
124
|
+
throw new Error(`Apex createCommExperiment failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
125
|
+
return res.json();
|
|
126
|
+
},
|
|
127
|
+
async startCommExperiment(id) {
|
|
128
|
+
const res = await fetch(`${root}/api/communications/experiments/${encodeURIComponent(id)}`, {
|
|
129
|
+
method: "PATCH", headers, body: JSON.stringify({ action: "start" }),
|
|
130
|
+
});
|
|
131
|
+
if (!res.ok)
|
|
132
|
+
throw new Error(`Apex startCommExperiment failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
133
|
+
},
|
|
134
|
+
async promoteCommExperimentWinner(id) {
|
|
135
|
+
const res = await fetch(`${root}/api/communications/experiments/${encodeURIComponent(id)}`, {
|
|
136
|
+
method: "PATCH", headers, body: JSON.stringify({ action: "promote" }),
|
|
137
|
+
});
|
|
138
|
+
if (!res.ok)
|
|
139
|
+
throw new Error(`Apex promoteCommExperimentWinner failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
140
|
+
},
|
|
141
|
+
// ─── Event Taxonomy ───────────────────────────────────────────────
|
|
142
|
+
async getEventTaxonomy() {
|
|
143
|
+
const res = await fetch(`${root}/api/communications/events`, { headers });
|
|
144
|
+
if (!res.ok)
|
|
145
|
+
throw new Error(`Apex getEventTaxonomy failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
146
|
+
return res.json();
|
|
147
|
+
},
|
|
148
|
+
async getEventIntegrationStatus() {
|
|
149
|
+
const res = await fetch(`${root}/api/communications/events/status`, { headers });
|
|
150
|
+
if (!res.ok)
|
|
151
|
+
throw new Error(`Apex getEventIntegrationStatus failed (${res.status}): ${await res.text().catch(() => "")}`);
|
|
152
|
+
return res.json();
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=management.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"management.js","sourceRoot":"","sources":["../src/management.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@apex-inc/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Apex Growth Intelligence SDK — track events, identify users, and run experiments from any JavaScript runtime.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/esm/index.js",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": ["dist", "skills"],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc && tsc -p tsconfig.esm.json",
|
|
18
|
+
"dev": "tsc --watch"
|
|
19
|
+
},
|
|
20
|
+
"keywords": ["apex", "growth", "analytics", "experiments", "ab-testing", "sdk"],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/apex-inc/sdk"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"typescript": "^5.7.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: apex-communications
|
|
3
|
+
description: Build lifecycle communication programs with Apex — automated emails, push notifications, A/B experiments, and event-driven triggers. Use when setting up user communications, onboarding emails, retention campaigns, or notification programs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Apex Communications (SDK)
|
|
7
|
+
|
|
8
|
+
Apex communications are lifecycle emails and push notifications that fire automatically when users hit key moments — signup, onboarding stall, trial expiring, feature discovery, churn risk. They're auto-generated for your vertical and conversion model, then customizable.
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
import { createManagementClient } from "@apex-inc/sdk";
|
|
14
|
+
|
|
15
|
+
const apex = createManagementClient({
|
|
16
|
+
projectKey: "proj_abc",
|
|
17
|
+
apiKey: "apex_ak_...",
|
|
18
|
+
apiUrl: "https://app.apex.inc",
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// 1. Get recommendations for your vertical
|
|
22
|
+
const recs = await apex.recommendCommunications();
|
|
23
|
+
|
|
24
|
+
// 2. Generate communications from recommendations
|
|
25
|
+
const comms = await apex.generateCommunications(["welcome", "onboarding_reminder", "trial_expiring"]);
|
|
26
|
+
|
|
27
|
+
// 3. See what events you need to track
|
|
28
|
+
const events = await apex.getEventTaxonomy();
|
|
29
|
+
|
|
30
|
+
// 4. Preview a communication
|
|
31
|
+
const preview = await apex.previewCommunication("tcomm_welcome");
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## The Event Taxonomy
|
|
35
|
+
|
|
36
|
+
Each vertical has a standard set of events that power communications. After generating your communication program, call `getEventTaxonomy()` to see what events to instrument:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
const events = await apex.getEventTaxonomy();
|
|
40
|
+
// Returns: [{ id: "user_signup", name: "User Signup", sdkExample: "apex.track('user_signup', { ... })" }, ...]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Add `apex.track()` calls at each trigger point in your app. Communications fire automatically when the matching event arrives.
|
|
44
|
+
|
|
45
|
+
## Managing Communications
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// List all communications
|
|
49
|
+
const comms = await apex.listCommunications();
|
|
50
|
+
|
|
51
|
+
// Update copy, channels, or status
|
|
52
|
+
await apex.updateCommunication("tcomm_welcome", {
|
|
53
|
+
content: { subject: "Welcome to Acme!", slots: { headline: "Let's get started" } },
|
|
54
|
+
channels: ["email", "in_app_push"],
|
|
55
|
+
status: "active",
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Send a test
|
|
59
|
+
await apex.sendTestCommunication("tcomm_welcome");
|
|
60
|
+
|
|
61
|
+
// Trigger for a specific user
|
|
62
|
+
await apex.triggerCommunication("tcomm_welcome", {
|
|
63
|
+
recipientEmail: "user@example.com",
|
|
64
|
+
mergeData: { user_name: "Alice" },
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Delete
|
|
68
|
+
await apex.deleteCommunication("tcomm_unused");
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Running Experiments
|
|
72
|
+
|
|
73
|
+
A/B test any communication's subject, body, CTA, or full content with Thompson Sampling:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// Create an experiment
|
|
77
|
+
const exp = await apex.createCommExperiment({
|
|
78
|
+
communicationId: "tcomm_welcome",
|
|
79
|
+
splitLevel: "subject",
|
|
80
|
+
funnelGoal: "onboarding_complete",
|
|
81
|
+
variants: [
|
|
82
|
+
{ name: "Control", subjectOverride: "Welcome to Acme" },
|
|
83
|
+
{ name: "Personal", subjectOverride: "Alice, welcome to Acme" },
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Start it
|
|
88
|
+
await apex.startCommExperiment(exp.id);
|
|
89
|
+
|
|
90
|
+
// Check results
|
|
91
|
+
const experiments = await apex.listCommExperiments();
|
|
92
|
+
|
|
93
|
+
// Promote the winner
|
|
94
|
+
await apex.promoteCommExperimentWinner(exp.id);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Integration Patterns
|
|
98
|
+
|
|
99
|
+
### Next.js (App Router)
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// app/api/auth/signup/route.ts
|
|
103
|
+
import { apex } from "@/lib/apex";
|
|
104
|
+
|
|
105
|
+
export async function POST(req) {
|
|
106
|
+
const user = await createUser(req);
|
|
107
|
+
apex.track("user_signup", { userId: user.id, email: user.email });
|
|
108
|
+
apex.identify(user.email, { name: user.name });
|
|
109
|
+
return Response.json(user);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Express
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
app.post("/api/purchase", async (req, res) => {
|
|
117
|
+
const order = await processOrder(req.body);
|
|
118
|
+
apex.track("purchase_complete", {
|
|
119
|
+
orderId: order.id,
|
|
120
|
+
amount: order.total,
|
|
121
|
+
userId: req.user.id,
|
|
122
|
+
});
|
|
123
|
+
res.json(order);
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Event Checklist
|
|
128
|
+
|
|
129
|
+
After setting up communications, verify these events are tracked:
|
|
130
|
+
|
|
131
|
+
1. `user_signup` — fires once per new user
|
|
132
|
+
2. `onboarding_complete` — fires when the user finishes setup
|
|
133
|
+
3. `feature_used` — fires on first or repeated feature interaction
|
|
134
|
+
4. `purchase_complete` — fires on conversion
|
|
135
|
+
5. Check `getEventIntegrationStatus()` to see which events Apex has received
|