UNPKG

mobiqo-react-native

Version:

Mobiqo SDK for Capacitor apps - Mobile analytics and user tracking

398 lines (397 loc) 17.7 kB
"use strict"; 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()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MobiqoEvent = void 0; const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage")); const react_native_1 = require("react-native"); var MobiqoEvent_1 = require("./MobiqoEvent"); Object.defineProperty(exports, "MobiqoEvent", { enumerable: true, get: function () { return MobiqoEvent_1.MobiqoEvent; } }); /** * Mobiqo Analytics Service for React Native 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-react-native'; * * 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' } * }); * 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) { yield async_storage_1.default.removeItem('mobiqo_project_id'); console.error('Project not found or not authorized'); return; } yield async_storage_1.default.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, install react-native-device-info: * npm install --save react-native-device-info * * @returns Device model string or 'unknown' if not available * @private */ getDeviceModel() { var _a, _b, _c; try { // Try to use react-native-device-info if available (optional peer dependency) try { const DeviceInfo = require('react-native-device-info'); // getModel() returns actual device model like "iPhone13,2" on iOS or "SM-G991B" on Android const model = ((_b = (_a = DeviceInfo.default) === null || _a === void 0 ? void 0 : _a.getModel) === null || _b === void 0 ? void 0 : _b.call(_a)) || ((_c = DeviceInfo.getModel) === null || _c === void 0 ? void 0 : _c.call(DeviceInfo)); if (model) { return model; } } catch (e) { // react-native-device-info not installed, fall back to Platform API } // Fallback: Use Platform constants const constants = react_native_1.Platform.constants; if (react_native_1.Platform.OS === 'ios') { // iOS: Try to get device info from constants // Note: This won't give hardware identifier without device-info package return constants.systemName || constants.model || react_native_1.Platform.OS; } else if (react_native_1.Platform.OS === 'android') { // Android: Try to extract model from constants return constants.Model || constants.Brand || react_native_1.Platform.OS; } return react_native_1.Platform.OS || '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.include_advanced_analysis - Whether to include advanced analysis in the response (purchase probability and other data, but request takes more time) * @param options.additional_data - Optional extra user data to store (email, name, 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: 'user@example.com', * referrer: 'google', * } * }); * * // 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 = yield async_storage_1.default.getItem('mobiqo_project_id'); if (!project_id) { console.error('Project ID not found'); return; } const device_model = 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, }; 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(); yield async_storage_1.default.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', * } * }); * ``` */ updateUser(_a) { return __awaiter(this, arguments, void 0, function* ({ revenue_cat_user_id, additional_data }) { try { const project_id = yield async_storage_1.default.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, }; 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 = yield async_storage_1.default.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 = yield async_storage_1.default.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 = yield async_storage_1.default.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) { yield async_storage_1.default.setItem('mobiqo_session_id', responseData.sessionId); } return responseData; } catch (error) { console.error('Error sending heartbeat:', error); } }); } } exports.default = Mobiqo;