diff --git a/src/Lib.ts b/src/Lib.ts index 884ae69..db6fd64 100644 --- a/src/Lib.ts +++ b/src/Lib.ts @@ -593,6 +593,108 @@ export class Lib { this.cachedData = null } + /** + * Gets the anonymous profile ID for the current visitor. + * If profileId was set via init options, returns that. + * Otherwise, requests server to generate one from IP/UA hash. + * + * This ID can be used for revenue attribution with payment providers. + * + * @returns A promise that resolves to the profile ID string, or null on error. + * + * @example + * ```typescript + * const profileId = await swetrix.getProfileId() + * + * // Pass to Paddle Checkout for revenue attribution + * Paddle.Checkout.open({ + * items: [{ priceId: 'pri_01234567890', quantity: 1 }], + * customData: { + * swetrix_profile_id: profileId, + * swetrix_session_id: await swetrix.getSessionId() + * } + * }) + * ``` + */ + async getProfileId(): Promise { + // If profileId is already set in options, return it + if (this.options?.profileId) { + return this.options.profileId + } + + if (!isInBrowser()) { + return null + } + + try { + const apiBase = this.getApiBase() + const response = await fetch(`${apiBase}/log/profile-id`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ pid: this.projectID }), + }) + + if (!response.ok) { + return null + } + + const data = (await response.json()) as { profileId: string | null } + return data.profileId + } catch { + return null + } + } + + /** + * Gets the current session ID for the visitor. + * Session IDs are generated server-side based on IP and user agent. + * + * This ID can be used for revenue attribution with payment providers. + * + * @returns A promise that resolves to the session ID string, or null on error. + * + * @example + * ```typescript + * const sessionId = await swetrix.getSessionId() + * + * // Pass to Paddle Checkout for revenue attribution + * Paddle.Checkout.open({ + * items: [{ priceId: 'pri_01234567890', quantity: 1 }], + * customData: { + * swetrix_profile_id: await swetrix.getProfileId(), + * swetrix_session_id: sessionId + * } + * }) + * ``` + */ + async getSessionId(): Promise { + if (!isInBrowser()) { + return null + } + + try { + const apiBase = this.getApiBase() + const response = await fetch(`${apiBase}/log/session-id`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ pid: this.projectID }), + }) + + if (!response.ok) { + return null + } + + const data = (await response.json()) as { sessionId: string | null } + return data.sessionId + } catch { + return null + } + } + /** * Gets the API base URL (without /log suffix). */ diff --git a/src/index.ts b/src/index.ts index b45f0b9..1b5c195 100644 --- a/src/index.ts +++ b/src/index.ts @@ -263,6 +263,63 @@ export function clearExperimentsCache(): void { LIB_INSTANCE.clearExperimentsCache() } +/** + * Gets the anonymous profile ID for the current visitor. + * If profileId was set via init options, returns that. + * Otherwise, requests server to generate one from IP/UA hash. + * + * This ID can be used for revenue attribution with payment providers like Paddle. + * + * @returns A promise that resolves to the profile ID string, or null on error. + * + * @example + * ```typescript + * const profileId = await getProfileId() + * + * // Pass to Paddle Checkout for revenue attribution + * Paddle.Checkout.open({ + * items: [{ priceId: 'pri_01234567890', quantity: 1 }], + * customData: { + * swetrix_profile_id: profileId, + * swetrix_session_id: await getSessionId() + * } + * }) + * ``` + */ +export async function getProfileId(): Promise { + if (!LIB_INSTANCE) return null + + return LIB_INSTANCE.getProfileId() +} + +/** + * Gets the current session ID for the visitor. + * Session IDs are generated server-side based on IP and user agent. + * + * This ID can be used for revenue attribution with payment providers like Paddle. + * + * @returns A promise that resolves to the session ID string, or null on error. + * + * @example + * ```typescript + * const sessionId = await getSessionId() + * + * // Pass to Paddle Checkout for revenue attribution + * Paddle.Checkout.open({ + * items: [{ priceId: 'pri_01234567890', quantity: 1 }], + * customData: { + * swetrix_profile_id: await getProfileId(), + * swetrix_session_id: sessionId + * } + * }) + * ``` + */ +export async function getSessionId(): Promise { + if (!LIB_INSTANCE) return null + + return LIB_INSTANCE.getSessionId() +} + export { LibOptions, TrackEventOptions,