UNPKG

mobiqo-capacitor

Version:

Mobiqo SDK for Capacitor apps - Mobile analytics and user tracking

434 lines (433 loc) 18.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MobiqoEvent = void 0; var MobiqoEvent_1 = require("./MobiqoEvent"); Object.defineProperty(exports, "MobiqoEvent", { enumerable: true, get: function () { return MobiqoEvent_1.MobiqoEvent; } }); /** * Mobiqo Analytics Service for Capacitor apps * * This service provides analytics tracking, user management, and session handling * for mobile applications using the Mobiqo platform. * * @example * ```typescript * import Mobiqo, { MobiqoEvent, SyncUserResponse, AppUser } from 'mobiqo-capacitor'; * * const mobiqo = new Mobiqo(); * await mobiqo.init({ mobiqoKey: 'your-api-key' }); * * // Sync user with optional additional data * const result: SyncUserResponse = await mobiqo.syncUser({ * revenue_cat_user_id: 'user-123', * include_advanced_analysis: true, * additional_data: { user_id: 'user-123', user_name: 'John Doe', user_email: 'john.doe@example.com', referrer: 'google', referrer_data: { campaign_id: 'camp-456' } } * }); * console.log('User OS:', result.appUser.os); * console.log('Purchase intent:', result.statistics.purchase_intent); * * // Track events with optional additional data * await mobiqo.trackEvent('button_clicked', MobiqoEvent.CLICK, { screen: 'home' }); * await mobiqo.trackEvent('screen_viewed', MobiqoEvent.SCREEN_VIEW); * ``` */ class Mobiqo { constructor() { this.API_URL = "https://us-central1-mobiqo-582b4.cloudfunctions.net"; this.heartbeatInterval = null; } /** * Initialize the Mobiqo service with your API key * * This method must be called before using any other Mobiqo features. * It validates your API key and stores the project ID for subsequent requests. * * @param options - Configuration options * @param options.mobiqoKey - Your Mobiqo API key from the dashboard * @returns Promise that resolves when initialization is complete * * @example * ```typescript * const mobiqo = new Mobiqo(); * await mobiqo.init({ mobiqoKey: 'your-mobiqo-api-key' }); * ``` */ init(_a) { return __awaiter(this, arguments, void 0, function* ({ mobiqoKey }) { try { const response = yield fetch(this.API_URL + "/init", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ mobiqoKey }) }); const responseData = yield response.json(); if (!responseData.authorized) { localStorage.removeItem('mobiqo_project_id'); console.error('Project not found or not authorized'); return; } localStorage.setItem('mobiqo_project_id', responseData.project.id); } catch (error) { console.error('Error initializing Mobiqo', error); return; } }); } /** * Get device model information * * Returns actual device model when possible. For best results with Capacitor, install @capacitor/device: * npm install @capacitor/device * * @returns Device model string or 'unknown' if not available * @private */ getDeviceModel() { return __awaiter(this, void 0, void 0, function* () { try { // Try to use @capacitor/device if available (optional peer dependency) try { // @ts-expect-error - Device is not defined in the global scope const { Device } = yield Promise.resolve().then(() => __importStar(require('@capacitor/device'))); const info = yield Device.getInfo(); // model returns actual device model like "iPhone13,2" on iOS or device model on Android if (info.model) { return info.model; } } catch (e) { // @capacitor/device not installed, fall back to user agent parsing } // Fallback: Use user agent parsing const userAgent = navigator.userAgent; // Try to extract device model from user agent // iOS devices const iosMatch = userAgent.match(/iPhone|iPad|iPod/); if (iosMatch) { return iosMatch[0]; } // Android devices - try to extract model const androidMatch = userAgent.match(/Android.*;\s*([^)]+)\s*Build/); if (androidMatch && androidMatch[1]) { return androidMatch[1].trim(); } // Fallback to platform return navigator.platform || 'unknown'; } catch (error) { console.error('Error getting device model:', error); return 'unknown'; } }); } /** * Sync user data with Mobiqo and start a tracking session * * This method links a RevenueCat user ID with Mobiqo analytics and starts * automatic heartbeat tracking (every 20 seconds). Call this after user login * or when you want to start tracking a user's session. * * @param options - User sync options * @param options.revenue_cat_user_id - The RevenueCat user identifier * @param options.additional_data - Optional extra user data to store (email, plan, etc.) * @returns Promise that resolves with user sync response including user data and statistics * * @example * ```typescript * // With additional data and advanced analysis * await mobiqo.syncUser({ * revenue_cat_user_id: 'user-123', * include_advanced_analysis: true, * additional_data: { * user_id: 'user-123', * user_name: 'John Doe', * user_email: 'john.doe@example.com', * referrer: 'google', * referrer_data: { campaign_id: 'camp-456' }, * } * }); * * // Without additional data and advanced analysis * await mobiqo.syncUser({ * revenue_cat_user_id: 'user-123' * }); * ``` */ syncUser(_a) { return __awaiter(this, arguments, void 0, function* ({ revenue_cat_user_id, include_advanced_analysis, additional_data }) { try { const project_id = localStorage.getItem('mobiqo_project_id'); if (!project_id) { console.error('Project ID not found'); return; } const device_model = yield this.getDeviceModel(); const additionalData = { id: additional_data === null || additional_data === void 0 ? void 0 : additional_data.user_id, name: additional_data === null || additional_data === void 0 ? void 0 : additional_data.user_name, email: additional_data === null || additional_data === void 0 ? void 0 : additional_data.user_email, referrer: additional_data === null || additional_data === void 0 ? void 0 : additional_data.referrer, referrer_data: additional_data === null || additional_data === void 0 ? void 0 : additional_data.referrer_data, }; const response = yield fetch(this.API_URL + "/linkUser", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ revenue_cat_user_id, project_id, include_advanced_analysis, personal_data: additionalData || {}, device_model, local_timestamp: new Date().getTime() }) }); const responseData = yield response.json(); localStorage.setItem('mobiqo_session_id', responseData.sessionId); // Initialize heartbeat interval if not already running if (!this.heartbeatInterval) { this.heartbeatInterval = setInterval(() => { this.sendHeartbeat(); }, 20000); // 20 seconds } return responseData; } catch (error) { console.error('Error linking user to Mobiqo', error); return; } }); } /** * Update user data in Mobiqo * * This method allows you to update additional user data for an existing user. * Use this when you want to update user information without creating a new session. * * @param options - User update options * @param options.revenue_cat_user_id - The RevenueCat user identifier * @param options.additional_data - Optional extra user data to update (email, name, etc.) * @returns Promise that resolves when the update is complete * * @example * ```typescript * // Update user data * await mobiqo.updateUser({ * revenue_cat_user_id: 'user-123', * additional_data: { * user_id: 'user-123', * user_name: 'John Doe', * user_email: 'john.doe@example.com', * referrer: 'google', * referrer_data: { campaign_id: 'camp-456' }, * } * }); * ``` */ updateUser(_a) { return __awaiter(this, arguments, void 0, function* ({ revenue_cat_user_id, additional_data }) { try { const project_id = localStorage.getItem('mobiqo_project_id'); if (!project_id) { console.error('Project ID not found'); return; } const additionalData = { id: additional_data === null || additional_data === void 0 ? void 0 : additional_data.user_id, name: additional_data === null || additional_data === void 0 ? void 0 : additional_data.user_name, email: additional_data === null || additional_data === void 0 ? void 0 : additional_data.user_email, referrer: additional_data === null || additional_data === void 0 ? void 0 : additional_data.referrer, referrer_data: additional_data === null || additional_data === void 0 ? void 0 : additional_data.referrer_data, }; const response = yield fetch(this.API_URL + "/updateUser", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ revenue_cat_user_id, project_id, personal_data: additionalData || {} }) }); yield response.json(); } catch (error) { console.error('Error updating user', error); } }); } /** * Retrieve user information from Mobiqo * * Fetches stored user data and analytics information for a specific user. * Useful for displaying user stats or personalizing the app experience. * * @param options - User lookup options * @param options.revenue_cat_user_id - The RevenueCat user identifier to look up * @param options.include_advanced_analysis - Whether to include advanced analysis in the response (purchase probability and other data, but request takes more time) * @returns Promise that resolves with user information including user data and statistics * * @example * ```typescript * const userInfo = await mobiqo.getUserInfo({ * revenue_cat_user_id: 'user-123', * include_advanced_analysis: true * }); * console.log('User OS:', userInfo.appUser.os); * console.log('Purchase intent:', userInfo.statistics.purchase_intent); * ``` */ getUserInfo(_a) { return __awaiter(this, arguments, void 0, function* ({ revenue_cat_user_id, include_advanced_analysis }) { try { const project_id = localStorage.getItem('mobiqo_project_id'); if (!project_id) { console.error('Project ID not found'); return; } const response = yield fetch(this.API_URL + "/getAppUser", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ revenue_cat_user_id, project_id, include_advanced_analysis }) }); const responseData = yield response.json(); return responseData; } catch (error) { console.error('Error getting user info', error); return; } }); } /** * Track a custom event with Mobiqo analytics * * Records user interactions, behaviors, and custom events for analytics. * Events are automatically timestamped and associated with the current user session. * * @param event - Name/identifier for the event (e.g., 'button_clicked', 'screen_viewed') * @param eventType - Type of event from MobiqoEvent enum (CLICK, SCREEN_VIEW, etc.) * @param additionalData - Optional custom data to attach to the event * @returns Promise that resolves with tracking confirmation * * @example * ```typescript * // Track a button click with additional data * await mobiqo.trackEvent( * 'subscribe_button_clicked', * MobiqoEvent.CLICK, * { * button_location: 'home_screen', * user_plan: 'free' * } * ); * * // Track a screen view without additional data * await mobiqo.trackEvent('settings_screen', MobiqoEvent.SCREEN_VIEW); * ``` */ trackEvent(event, eventType, additionalData) { return __awaiter(this, void 0, void 0, function* () { try { additionalData = additionalData || {}; const session_id = localStorage.getItem('mobiqo_session_id'); if (!session_id) { console.error('Session ID not found'); return; } additionalData.local_timestamp = new Date().getTime(); const response = yield fetch(this.API_URL + "/trackEvent", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ event_name: event, event_type: eventType, session_id, additional_data: additionalData }) }); const responseData = yield response.json(); return responseData; // send event // additionalData is a dictionary of key-value pairs that will be sent to the Mobiqo API // additionalData will be sent to the Mobiqo API as a JSON object // additionalData will be sent to the Mobiqo API as a JSON object } catch (error) { console.error('Error tracking event', error); return; } }); } /** * Send a heartbeat to maintain the user session * * Heartbeats are automatically sent every 20 seconds after syncUser() is called. * This helps track active session duration and is handled internally by the SDK. * * @returns Promise that resolves with heartbeat confirmation * @private */ sendHeartbeat() { return __awaiter(this, void 0, void 0, function* () { try { const session_id = localStorage.getItem('mobiqo_session_id'); if (!session_id) { console.error('Session ID not found'); return; } const response = yield fetch(this.API_URL + "/heartbeat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ session_id }) }); const responseData = yield response.json(); // Update session ID if a new one is provided if (responseData.sessionId) { localStorage.setItem('mobiqo_session_id', responseData.sessionId); } return responseData; } catch (error) { console.error('Error sending heartbeat:', error); } }); } } exports.default = Mobiqo;