TypeScript SDK
Isang package na may anim na entry point. I-import ang tumutugma sa iyong runtime, at iiwan ng tree-shaken na build ang iba sa labas ng iyong bundle.
Saan ito nakalathala
@prodantix/sdk on npm.
I-install
bun add @prodantix/sdkMga entry point
Bawat subpath ay may sariling ESM at CommonJS na build kasama ang sariling mga type. Runtime agnostic ang root, at idinaragdag ng iba ang kailangan ng isang partikular na runtime.
| Subpath | What it exports |
|---|---|
| @prodantix/sdk | ProdantixClient, createClient, evaluateFlag, FlagsClient, MessagesClient |
| @prodantix/sdk/web | createWebClient, installAutocapture, installLinkCarry, installSessionReplay, WebTransport |
| @prodantix/sdk/node | createNodeClient, readSharedIdentity |
| @prodantix/sdk/csp | prodantixConnectSrc, prodantixImgSrc, prodantixScriptSrc |
| @prodantix/sdk/chat | mountChat, ChatClient, ChatPanel, resolveAppearance |
| @prodantix/sdk/messenger | fetchMessengerConfig, cachedMessengerConfig, MESSENGER_CACHE_KEY |
@prodantix/sdk
Ang client, ang tagatasa ng flag, at ang mga interface para sa storage at transport. Walang anumang humahawak sa DOM dito, kaya puwede kang magbigay ng sarili mong storage, transport, orasan o id factory at patakbuhin ito kahit saan.
import { createClient, MemoryStorage } from '@prodantix/sdk';
const prodantix = createClient({
apiKey: PRODANTIX_PUBLIC_KEY,
host: 'https://eu.api.prodantix.com',
storage: new MemoryStorage(),
});
prodantix.capture('order.completed', { properties: { amount: 4200, currency: 'XAF' } });
await prodantix.flush();@prodantix/sdk/web
Kableng pang-browser sa ibabaw ng parehong client: pananatili sa local storage, paghahatid sa pamamagitan ng beacon kapag itinago ang pahina, at autocapture ng pageview at click. Nananatiling naka-off ang session replay hangga't wala kang ibinibigay na replay host.
import { createWebClient } from '@prodantix/sdk/web';
const prodantix = createWebClient({
apiKey: PRODANTIX_PUBLIC_KEY,
host: 'https://eu.api.prodantix.com',
flagsHost: 'https://api.prodantix.com',
cookieDomain: 'example.com',
autocaptureOptions: { clicks: true, pageviews: true },
});
prodantix.identify('user-42', { set: { plan: 'pro' } });
if (await prodantix.isFeatureEnabled('new-checkout')) {
// ...
}
// Every per-flag read records one $feature_flag_called exposure.
const variant = await prodantix.getVariant('new-checkout');
if (variant?.key === 'treatment') {
// ...
}
// A flag targeting a cohort reads this user's memberships from the store;
// pass them yourself to skip the lookup.
if (await prodantix.isFeatureEnabledLocal('members', { cohorts: ['<cohort id>'] })) {
// ...
}Sa web, ang anonymous id at session ng bisita ay nasa iisang first-party cookie sa iyong registrable domain, kaya iisang tao ang nakikita ng xyz.com, app.xyz.com at console.xyz.com: ang marketing visit, ang sign-up at ang unang session sa app ay nasa iisang timeline sa sandaling kilalanin sila ng app. Ang identified id ay nananatili sa local storage ng bawat origin at hindi kailanman pumapasok sa cookie, dahil nababasa ito ng bawat host sa ilalim ng domain. Nahahanap ang domain sa pagtatanong sa browser, o itinatakda sa cookieDomain; ang site na ang mga subdomain ay pag-aari ng magkakaibang tenant ay dapat itakda ito sa sarili nitong host. Ipasa ang sharedStorage para hindi magsulat ng cookie, halimbawa hangga't walang pahintulot, at nananatiling fallback ang local storage kapag tinanggihan ang cookies. May session id na nililikha bawat pagbisita, pinapalitan pagkatapos ng tatlumpung minutong pagkakatahimik o dalawampu't apat na oras, itinatatak sa bawat event at ibinabahagi sa session replay.
Hindi kayang tumawid ng cookie sa isang registrable domain, kaya ang bisitang sumusunod sa isang link mula sa isang site papunta sa iba ay magiging dalawang bisita. Ipasa ang linkedDomains, walang laman bilang default, at pagagandahin ng client ang mga papalabas na link patungo sa mga domain na iyon, sa click at auxclick, gamit ang isang _pdx parameter na may dalang tatlong bagay: ang anonymous id, ang session id at ang sandaling nagsimula ang session, para magpatuloy ang tatlumpung-minutong bintana at ang dalawampu't apat na oras na hangganan sa kabila ng paglukso. Ang anonymous id lang ang naglalakbay, hindi kailanman ang identified, dahil ang patutunguhan mismo ang kikilala sa tao. Ang link papunta sa parehong registrable domain, ang may dalang _pdx na, at ang mailto, tel, javascript at hash na link ay iniiwang buo. Pagdating, binabasa ng createWebClient ang _pdx bago itayo ang pagkakakilanlan, isinusulat ang dalang id at session sa shared store, at inaalis ang parameter sa pamamagitan ng history.replaceState kaya hindi ito lumalabas sa $current_url at hindi rin sumasakay pasulong; ang parameter na hindi mabasa ang tatlong bahagi ay binabalewala at iniiwan ang address gaya ng dati. Kung may hawak nang ibang anonymous id ang host na ito, magpapadala ang client ng $create_alias, kaya ang naitala noon ay natutupi sa dalang id; at ang host na kumilala na sa isang tao ay pinapanatili ang taong iyon: ang dalang id ang nagiging anonymous id niya, hindi kailanman ang distinct id niya.
import { createWebClient } from '@prodantix/sdk/web';
const prodantix = createWebClient({
apiKey: PRODANTIX_PUBLIC_KEY,
host: 'https://eu.api.prodantix.com',
linkedDomains: ['example.com', 'example-app.com'],
});
// A link to example-app.com now leaves as
// https://example-app.com/pricing?_pdx=<anonymousId>~<sessionId>~<startedAt>
// and the arriving page adopts it before it builds an identity of its own.
// The visitor's answer, from your own consent banner.
prodantix.setConsent({ identityLink: false });
prodantix.consent(); // { identityLink: false }Ang sariling sagot ng bisita tungkol sa pagsasanib na iyon ay sumasakay sa parehong shared store, sa ilalim ng pdx..consent, kaya iisang sagot ang nakikita ng bawat subdomain at ng server na bumabasa ng cookie. Itala ito gamit ang setConsent({ identityLink: false }), basahin muli gamit ang consent(), at ihasik ito sa pamamagitan ng opsyong consent kapag hawak na ng app mo ang sagot: sa iyo ang paggawa ng consent banner, at iginagalang ng prodantix ang nakalap nito. Habang false ang identityLink, walang ipinapadalang anonymous id ang identify para isanib sa tao, at hindi pinapalamutian ang link papunta sa isang nakalistang domain, dahil ang pagdadala ng id papunta roon ay iyon ding pagsasanib sa ibang daan. Ang hindi nakatakda o true ay pumapayag sa dalawa, batay pa rin sa sariling setting ng proyekto sa console, na ipinapatupad ng state worker at hindi ng anumang ipinapadala ng browser. Ang pagbabago ng sagot ay umiiral sa susunod na identify at sa susunod na pag-click; walang naisanib na nabubuwag.
@prodantix/sdk/node
Ang parehong client na may mga default na pang-server. Ini-buffer ang mga event at ipinapadala sa background, kaya tawagin ang shutdown bago lumabas ang proseso o hindi kailanman aalis ang huling batch.
import { createNodeClient } from '@prodantix/sdk/node';
// A node client streams flag changes over Socket.IO by default and refetches
// the snapshot on push; streamFlags: false leaves only the 30s poll.
const prodantix = createNodeClient({
apiKey: process.env.PRODANTIX_PUBLIC_KEY,
host: 'https://eu.api.prodantix.com',
streamFlags: true,
});
prodantix.capture('job.completed', { properties: { queue: 'emails' } });
await prodantix.shutdown();Ang sign-in na natatapos sa isang server redirect ay walang ipinipintang pahina, kaya hindi kailanman tumatakbo roon ang sariling identify ng browser. Binabasa ng readSharedIdentity(cookieHeader, apiKey) ang cookie na isinulat ng web client at isinasagot nito ang anonymous id, ang session na kinaroroonan nito at ang pahintulot ng bisita, o null kapag wala ang cookie o hindi ito sa SDK na ito. Pagkatapos ay ipinapadala ng link(distinctId, anonymousId, traits) ang iisang $identify na sana'y ipinadala ng browser, para sa mga id na ibinigay, at hindi ginagalaw ang sariling pagkakakilanlan ng client na ito. Tinatawag ng login ng Bomdisoft ang dalawa sa pagkumpleto ng sign-in, sa loob ng iisang function na tinatawag na ng lahat ng walong sign-in site nito: doon unang nalalaman sa server ang subject ng tao habang nasa request pa ang cookie. Anim sa mga site na iyon ay server action na walang request object, kaya kumukuha ang function ng cookie header string sa halip na request. Laktawan ang link kapag ang sagot na nabasa ay identityLink false.
import { createNodeClient, readSharedIdentity } from '@prodantix/sdk/node';
const prodantix = createNodeClient({
apiKey: PRODANTIX_PUBLIC_KEY,
host: 'https://eu.api.prodantix.com',
});
// At sign-in completion, where the person is known and the browser's
// cookie is still on the request.
export const completeSignIn = (sub: string, cookieHeader: string): void => {
const shared = readSharedIdentity(cookieHeader, PRODANTIX_PUBLIC_KEY);
if (shared !== null && shared.consent?.identityLink !== false) {
prodantix.link(sub, shared.anonymousId);
}
};@prodantix/sdk/csp
Ang mga pinagmulan ng content security policy na kailangan ng isang app para maabot ang Prodantix. Wala itong ini-import mula sa React o sa browser, kaya direktang mababasa ito ng isang build config file.
import { prodantixConnectSrc, prodantixImgSrc, prodantixScriptSrc } from '@prodantix/sdk/csp';
const hosts = {
ingest: 'https://eu.api.prodantix.com',
edge: 'https://eu.edge.prodantix.com',
replay: 'https://eu.replay.prodantix.com',
};
const policy = [
`connect-src ${prodantixConnectSrc(hosts)}`,
`script-src ${prodantixScriptSrc(hosts)}`,
`img-src ${prodantixImgSrc(hosts, ["'self'", 'data:'])}`,
].join('; ');Ipinapakita ng widget ng suporta ang mga larawan ng iyong team mula sa edge at iginuguhit ang mga file na ipinapadala ng mga bisita mula sa mga address na blob:, kaya kailangan ng img-src ng policy ang dalawa. Idinadagdag ng prodantixImgSrc ang mga ito sa mga pinagmulan ng larawan na pinapayagan mo na. Kung wala ang mga ito, haharangin ng browser ang mga larawang iyon at sa sarili lang nitong console ito sasabihin.
@prodantix/sdk/chat
Ang widget ng suporta. I-mount ito at makakakuha ka ng handle na nagbubukas, nagsasara, sumisira, at nagpapakilala ng user. Nagre-render ito sa loob ng saradong shadow root, kaya hindi kailanman naaabot ito ng mga estilo ng host page.
import { mountChat } from '@prodantix/sdk/chat';
const messenger = mountChat({
apiKey: PRODANTIX_PUBLIC_KEY,
host: 'https://eu.edge.prodantix.com',
distinctId: prodantix.distinctId,
});
document.querySelector('#help')?.addEventListener('click', () => messenger.open());Bawat mensahe ng bisita ay may dalang kung saan ito isinulat. Binabasa ng panel ang location at document.title sa sandali ng pagpapadala at ipinapadala ang host, path at title, kung saan ang path ay ang pathname lamang: hindi kailanman ang query at hindi kailanman ang fragment, dahil ang isang reset link, isang magic link o isang pagbalik mula sa checkout ay may dalang token doon at hindi lugar niyon ang inbox ng ahente. Wala ritong ipinipinta ang panel, kaya nananatiling sariling salita ng bisita ang kanyang thread, at inaalis din ito ng sagot ng edge pabalik sa SDK, kaya hindi makikita ng isang pahinang bumabasa ng sariling thread ang nakikita ng console. Kung saan ito lumilitaw ay sa inbox, bilang isang mahinang linya sa ilalim ng papasok na turn.
@prodantix/sdk/messenger
Ang tagabasa ng setting sa likod ng widget: kinukuha nito ang konfigurasyon ng messenger para sa isang proyekto, kina-cache ito, at sinasabi kung naka-on ang messenger sa proyekto. Hiwalay na binubuo ang self-executing na snippet at hindi ito maaabot sa pamamagitan ng subpath na ito.
import { fetchMessengerConfig } from '@prodantix/sdk/messenger';
const config = await fetchMessengerConfig({
apiKey: PRODANTIX_PUBLIC_KEY,
host: 'https://eu.edge.prodantix.com',
});
if (config?.enabled) {
// the project has the messenger switched on
}