TypeScript SDK
एक पैकेज, छह प्रवेश बिंदु। जो आपके रनटाइम से मेल खाता है उसे इंपोर्ट करें, और ट्री-शेकिंग बिल्ड बाकी को आपके बंडल से बाहर छोड़ देता है।
कहाँ प्रकाशित है
@prodantix/sdk on npm.
इंस्टॉल
bun add @prodantix/sdkप्रवेश बिंदु
हर सबपाथ अपनी ESM और CommonJS बिल्ड अपने टाइप्स के साथ भेजता है। रूट रनटाइम-निरपेक्ष है, और बाकी वह जोड़ते हैं जो किसी एक रनटाइम को चाहिए।
| 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
क्लाइंट, फ़्लैग मूल्यांकनकर्ता, और स्टोरेज तथा ट्रांसपोर्ट इंटरफ़ेस। यहाँ कुछ भी DOM को नहीं छूता, इसलिए आप अपना स्टोरेज, ट्रांसपोर्ट, क्लॉक या आईडी फ़ैक्ट्री देकर इसे कहीं भी चला सकते हैं।
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
उसी क्लाइंट के ऊपर ब्राउज़र वायरिंग: लोकल स्टोरेज में स्थायित्व, पेज छिपने पर बीकन से डिलीवरी, और पेजव्यू तथा क्लिक का ऑटोकैप्चर। जब तक आप रीप्ले होस्ट नहीं देते, सेशन रीप्ले बंद रहता है।
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>'] })) {
// ...
}वेब पर विज़िटर की अनाम आईडी और सेशन आपके पंजीकरण-योग्य डोमेन पर एक ही फ़र्स्ट-पार्टी कुकी में रहते हैं, इसलिए xyz.com, app.xyz.com और console.xyz.com एक ही व्यक्ति देखते हैं: मार्केटिंग विज़िट, साइन-अप और ऐप का पहला सेशन एक ही टाइमलाइन पर आ जाते हैं, जैसे ही ऐप उसे पहचान लेता है। पहचानी गई आईडी हर ऑरिजिन पर लोकल स्टोरेज में रहती है और कभी कुकी में नहीं जाती, क्योंकि डोमेन के नीचे का हर होस्ट उसे पढ़ सकता है। डोमेन ब्राउज़र से पूछकर मिलता है, या cookieDomain से तय होता है; जिस साइट के सबडोमेन अलग-अलग टेनेंट के हों, उसे इसे अपने ही होस्ट पर सेट करना होगा। कोई कुकी न लिखने के लिए sharedStorage दें, जैसे सहमति मिलने तक, और कुकी अस्वीकार होने पर लोकल स्टोरेज ही फ़ॉलबैक रहता है। हर विज़िट पर एक सेशन आईडी बनती है, तीस मिनट निष्क्रियता या चौबीस घंटे बाद बदलती है, हर इवेंट पर लगती है और सेशन रीप्ले के साथ साझा होती है।
कोई कुकी पंजीकरण-योग्य डोमेन पार नहीं कर सकती, इसलिए एक साइट से दूसरी साइट का लिंक खोलने वाला विज़िटर दो विज़िटर बन जाता। linkedDomains दें, जो डिफ़ॉल्ट रूप से खाली है, और क्लाइंट उन डोमेन की ओर जाने वाले लिंक को click और auxclick पर एक _pdx पैरामीटर से सजाता है; वह पैरामीटर तीन चीज़ें ले जाता है: अनाम आईडी, सेशन आईडी और सेशन शुरू होने का क्षण, ताकि तीस मिनट की खिड़की और चौबीस घंटे की सीमा उस छलांग के बाद भी चलती रहे। केवल अनाम आईडी जाती है, पहचानी गई आईडी कभी नहीं, क्योंकि गंतव्य स्वयं उस व्यक्ति को पहचान लेता है। उसी पंजीकरण-योग्य डोमेन का लिंक, जिसमें पहले से _pdx है वह लिंक, तथा mailto, tel, javascript और hash लिंक सभी अछूते रहते हैं। पहुँचने पर createWebClient पहचान बनने से पहले _pdx पढ़ता है, लाई गई आईडी और सेशन को साझा स्टोर में लिखता है, और history.replaceState से पैरामीटर हटा देता है, ताकि वह न $current_url में दिखे और न आगे जाए; जिस पैरामीटर के तीनों हिस्से न पढ़े जाएँ उसे अनदेखा कर दिया जाता है और पता जैसा था वैसा ही रहता है। यदि इस होस्ट के पास पहले से कोई दूसरी अनाम आईडी थी, तो क्लाइंट $create_alias भेजता है, जिससे पहले दर्ज हुआ सब कुछ लाई गई आईडी में समा जाता है; और जिस होस्ट ने पहले ही किसी व्यक्ति को पहचान लिया है वह उस व्यक्ति को बनाए रखता है: लाई गई आईडी उनकी अनाम आईडी बनती है, उनकी distinct आईडी कभी नहीं।
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 }उस जोड़ के बारे में विज़िटर का अपना उत्तर उसी साझा स्टोर में, pdx..consent के नीचे चलता है, इसलिए हर सबडोमेन और कुकी पढ़ने वाला सर्वर एक ही उत्तर देखते हैं। इसे setConsent({ identityLink: false }) से दर्ज करें, consent() से वापस पढ़ें, और जब आपका ऐप उत्तर पहले से रखता हो तो consent विकल्प से बो दें: सहमति बैनर आपको बनाना है, और prodantix उसके एकत्र किए उत्तर का सम्मान करता है। जब तक identityLink false है, identify व्यक्ति से जोड़ने के लिए कोई अनाम आईडी नहीं भेजता, और सूचीबद्ध डोमेन का लिंक बिना सजावट के रहता है, क्योंकि आईडी को पार ले जाना वही जोड़ है, बस दूसरे रास्ते से। अनसेट या true दोनों की अनुमति देते हैं, पर कंसोल में प्रोजेक्ट की अपनी सेटिंग के अधीन, जिसे स्टेट वर्कर लागू करता है, ब्राउज़र का भेजा कुछ नहीं। उत्तर बदलना अगले identify और अगले क्लिक पर लागू होता है; पहले से जुड़ा कुछ भी अलग नहीं किया जाता।
@prodantix/sdk/node
वही क्लाइंट, सर्वर के डिफ़ॉल्ट के साथ। इवेंट बफ़र होते हैं और पृष्ठभूमि में भेजे जाते हैं, इसलिए प्रोसेस समाप्त होने से पहले shutdown कॉल करें, वरना आख़िरी बैच कभी नहीं जाएगा।
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();जो साइन-इन सर्वर रीडायरेक्ट में पूरा होता है वह कोई पेज नहीं बनाता, इसलिए ब्राउज़र का अपना identify वहाँ कभी नहीं चलता। readSharedIdentity(cookieHeader, apiKey) वेब क्लाइंट की लिखी कुकी पढ़ता है और अनाम आईडी, वह जिस सेशन में है, तथा विज़िटर की सहमति लौटाता है, या कुकी न होने पर अथवा वह इस SDK की न होने पर null देता है। फिर link(distinctId, anonymousId, traits) वही एक $identify भेजता है जो ब्राउज़र भेजता, दी गई आईडी के लिए, और इस क्लाइंट की अपनी पहचान को छूता नहीं। Bomdisoft का लॉगिन साइन-इन पूरा होने पर दोनों को बुलाता है, उसी एक फ़ंक्शन के भीतर जिसे उसकी आठों साइन-इन जगहें पहले से बुलाती हैं: वहीं व्यक्ति का subject सर्वर पर पहली बार ज्ञात होता है और कुकी अब भी अनुरोध पर होती है। उनमें से छह जगहें ऐसी सर्वर क्रियाएँ हैं जिनके पास कोई अनुरोध वस्तु नहीं, इसीलिए फ़ंक्शन अनुरोध नहीं बल्कि कुकी हेडर स्ट्रिंग लेता है। पढ़कर मिला उत्तर identityLink false हो तो link छोड़ दें।
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
किसी ऐप को Prodantix तक पहुँचने के लिए जिन कंटेंट सिक्योरिटी पॉलिसी स्रोतों की ज़रूरत होती है। यह React या ब्राउज़र से कुछ भी इंपोर्ट नहीं करता, इसलिए बिल्ड कॉन्फ़िग फ़ाइल इसे सीधे पढ़ सकती है।
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('; ');सपोर्ट विजेट आपकी टीम की तस्वीरें edge से दिखाता है और विज़िटर्स की भेजी फ़ाइलें blob: पतों से बनाता है, इसलिए पॉलिसी के img-src में दोनों चाहिए। prodantixImgSrc इन्हें उन इमेज स्रोतों में जोड़ता है जिनकी आप पहले से अनुमति देते हैं। इनके बिना ब्राउज़र उन तस्वीरों को रोक देता है और यह सिर्फ़ अपने कंसोल में बताता है।
@prodantix/sdk/chat
सपोर्ट विजेट। इसे माउंट करें और आपको एक हैंडल मिलता है जो खोलता, बंद करता, नष्ट करता और उपयोगकर्ता की पहचान कराता है। यह एक बंद शैडो रूट के भीतर रेंडर होता है, इसलिए होस्ट पेज की शैलियाँ इस तक कभी नहीं पहुँचतीं।
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());हर विज़िटर संदेश यह लेकर चलता है कि वह कहाँ लिखा गया। पैनल भेजने के क्षण में location और document.title पढ़ता है और host, path तथा title भेजता है, जिसमें path केवल पथनाम है: कभी क्वेरी नहीं और कभी फ़्रैगमेंट नहीं, क्योंकि रीसेट लिंक, मैजिक लिंक या चेकआउट से वापसी अपना टोकन वहीं रखते हैं, और एजेंट का इनबॉक्स उसकी जगह नहीं है। पैनल इसमें से कुछ नहीं बनाता, इसलिए विज़िटर का थ्रेड उसके अपने शब्द ही रहता है; एज का SDK को दिया गया उत्तर भी इसे छोड़ देता है, इसलिए अपना ही थ्रेड पढ़ रहा कोई पेज वह नहीं देख सकता जो कंसोल देखता है। यह दिखता है इनबॉक्स में, किसी आवक संदेश के नीचे एक धीमी पंक्ति के रूप में।
@prodantix/sdk/messenger
विजेट के पीछे का सेटिंग रीडर: यह किसी प्रोजेक्ट का मैसेंजर कॉन्फ़िगरेशन लाता है, उसे कैश करता है, और बताता है कि प्रोजेक्ट ने मैसेंजर चालू रखा है या नहीं। स्वतः चलने वाला स्निपेट अलग से बनता है और इस सबपाथ से नहीं मिलता।
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
}