UNPKG

tracker-api

Version:

A comprehensive JavaScript/TypeScript library for user behavior tracking and analytics

698 lines (626 loc) 20.4 kB
// index.ts - Main entry point for the tracking library import { TrackingAPI } from "./tracking-api"; import { TrackerOptions, EventData, TrackingResponse } from "./types"; import { TrackerEnum } from "./tracker.enum"; // Singleton instance for global usage let globalTracker: TrackingAPI | null = null; /** * Initialize global tracker instance * @param options - Configuration options * @returns Tracker instance */ export function init(options: TrackerOptions = {}): TrackingAPI { // Support for direct API configuration (for JavaScript environments) const mergedOptions: TrackerOptions = { ...options, // Use provided apiKey or trackingApiKey first, then fallback to env apiKey: options.apiKey || options.trackingApiKey || (typeof process !== "undefined" && process.env ? process.env.NEXT_PUBLIC_TRACKING_API_KEY : undefined), // Use provided baseUrl or apiUrl first, then fallback to env baseUrl: options.baseUrl || options.apiUrl || (typeof process !== "undefined" && process.env ? process.env.NEXT_PUBLIC_API_URL : undefined), }; globalTracker = new TrackingAPI(mergedOptions); return globalTracker; } /** * Get global tracker instance * @returns Global tracker instance */ export function getTracker(): TrackingAPI | null { if (!globalTracker) { // Auto-initialize with environment variables if available const defaultApiKey = typeof process !== "undefined" && process.env ? process.env.NEXT_PUBLIC_TRACKING_API_KEY : undefined; const defaultApiUrl = typeof process !== "undefined" && process.env ? process.env.NEXT_PUBLIC_API_URL : undefined; globalTracker = new TrackingAPI({ apiKey: defaultApiKey, baseUrl: defaultApiUrl, }); } return globalTracker; } /** * Create new tracker instance (không dùng global) * @param options - Configuration options * @returns New tracker instance */ export function createTracker(options: TrackerOptions = {}): TrackingAPI { return new TrackingAPI(options); } // Convenience functions using global tracker for quick tracking /** * Track a custom event using global tracker */ export async function track( eventData: EventData, immediate: boolean = false ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; return await tracker.track(eventData, immediate); } /** * Track multiple events at once using global tracker */ export async function trackBatch( events: EventData[] ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; return await tracker.trackBatch(events); } // ===== EVENT TYPE SPECIFIC TRACKING FUNCTIONS ===== // Dựa theo TrackerEnum.EventType để tạo các hàm tracking cụ thể /** * Track page view event - TrackerEnum.EventType.pageview */ export async function trackPageView( eventData: Partial<EventData> & { page_url: string; page_title?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.pageview, event_name: eventData.event_name || TrackerEnum.EventName.view_product, event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } /** * Track click event - TrackerEnum.EventType.click */ export async function trackClick( eventData: Partial<EventData> & { page_url: string; element_selector?: string; element_text?: string; element_id?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.click, event_name: eventData.event_name || TrackerEnum.EventName.button_click, visitor_id: eventData.visitor_id || "", // Will be handled by tracking-client event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), ...eventData, }; return await tracker.track(fullEventData); } /** * Track input event - TrackerEnum.EventType.input */ export async function trackInput( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.input, event_name: eventData.event_name || TrackerEnum.EventName.form_input_change, visitor_id: eventData.visitor_id || "", // Will be handled by tracking-client event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), ...eventData, }; return await tracker.track(fullEventData); } /** * Track submit event - TrackerEnum.EventType.submit */ export async function trackSubmit( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.submit, event_name: eventData.event_name || TrackerEnum.EventName.contact_form_submit, visitor_id: eventData.visitor_id || "", // Will be handled by tracking-client event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), ...eventData, }; return await tracker.track(fullEventData); } /** * Track scroll event - TrackerEnum.EventType.scroll */ export async function trackScroll( eventData: Partial<EventData> & { page_url: string; properties?: Record<string, string>; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.scroll, event_name: eventData.event_name || TrackerEnum.EventName.scroll_to_bottom, visitor_id: eventData.visitor_id || "", // Will be handled by tracking-client event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), ...eventData, }; return await tracker.track(fullEventData); } /** * Track hover event - TrackerEnum.EventType.hover */ export async function trackHover( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.hover, event_name: eventData.event_name || "Element Hover", event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } /** * Track change event - TrackerEnum.EventType.change */ export async function trackChange( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.change, event_name: eventData.event_name || TrackerEnum.EventName.form_input_change, event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } /** * Track focus event - TrackerEnum.EventType.focus */ export async function trackFocus( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.focus, event_name: eventData.event_name || "Element Focus", event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } /** * Track blur event - TrackerEnum.EventType.blur */ export async function trackBlur( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.blur, event_name: eventData.event_name || "Element Blur", event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } /** * Track keydown event - TrackerEnum.EventType.keydown */ export async function trackKeydown( eventData: Partial<EventData> & { page_url: string; element_selector?: string; properties?: Record<string, string>; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.keydown, event_name: eventData.event_name || "Key Press", event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } /** * Track keyup event - TrackerEnum.EventType.keyup */ export async function trackKeyup( eventData: Partial<EventData> & { page_url: string; element_selector?: string; properties?: Record<string, string>; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.keyup, event_name: eventData.event_name || "Key Release", event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } /** * Track mouseenter event - TrackerEnum.EventType.mouseenter */ export async function trackMouseenter( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.mouseenter, event_name: eventData.event_name || "Mouse Enter", event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } /** * Track mouseleave event - TrackerEnum.EventType.mouseleave */ export async function trackMouseleave( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.mouseleave, event_name: eventData.event_name || "Mouse Leave", event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } /** * Track zoom event - TrackerEnum.EventType.zoom */ export async function trackZoom( eventData: Partial<EventData> & { page_url: string; properties?: Record<string, string>; } ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; const fullEventData: EventData = { event_type: TrackerEnum.EventType.zoom, event_name: eventData.event_name || "Page Zoom", event_date: eventData.event_date || new Date().toISOString().split("T")[0], event_time: eventData.event_time || new Date().toISOString(), visitor_id: "", // Will be handled by tracking-client ...eventData, }; return await tracker.track(fullEventData); } // ===== BUSINESS SPECIFIC EVENT FUNCTIONS ===== // Các hàm tracking cho business events cụ thể /** * Track login form submission */ export async function trackLoginFormSubmit( eventData: Partial<EventData> & { page_url: string; } ): Promise<TrackingResponse | null> { return await trackSubmit({ ...eventData, event_name: TrackerEnum.EventName.login_form_submit, element_selector: eventData.element_selector || TrackerEnum.ElementSelector.login_button, element_text: eventData.element_text || TrackerEnum.ElementText.login, }); } /** * Track signup form submission */ export async function trackSignupFormSubmit( eventData: Partial<EventData> & { page_url: string; } ): Promise<TrackingResponse | null> { return await trackSubmit({ ...eventData, event_name: TrackerEnum.EventName.signup_form_submit, element_selector: eventData.element_selector || TrackerEnum.ElementSelector.signup_button, element_text: eventData.element_text || TrackerEnum.ElementText.signup, }); } /** * Track search query submission */ export async function trackSearchQuerySubmit( eventData: Partial<EventData> & { page_url: string; properties?: Record<string, string>; } ): Promise<TrackingResponse | null> { return await trackSubmit({ ...eventData, event_name: TrackerEnum.EventName.search_query_submit, element_selector: eventData.element_selector || TrackerEnum.ElementSelector.search_input, element_text: eventData.element_text || TrackerEnum.ElementText.search, }); } /** * Track add to cart action */ export async function trackAddToCart( eventData: Partial<EventData> & { page_url: string; properties?: Record<string, string>; } ): Promise<TrackingResponse | null> { return await trackClick({ ...eventData, event_name: TrackerEnum.EventName.add_to_cart, element_selector: eventData.element_selector || TrackerEnum.ElementSelector.add_to_cart_button, element_text: eventData.element_text || TrackerEnum.ElementText.add_to_cart, }); } /** * Track remove from cart action */ export async function trackRemoveFromCart( eventData: Partial<EventData> & { page_url: string; properties?: Record<string, string>; } ): Promise<TrackingResponse | null> { return await trackClick({ ...eventData, event_name: TrackerEnum.EventName.remove_from_cart, element_text: eventData.element_text || TrackerEnum.ElementText.remove, }); } /** * Track purchase event */ export async function trackPurchase( eventData: Partial<EventData> & { page_url: string; properties?: Record<string, string>; } ): Promise<TrackingResponse | null> { return await trackSubmit({ ...eventData, event_name: TrackerEnum.EventName.purchase, }); } /** * Track contact form submission */ export async function trackContactFormSubmit( eventData: Partial<EventData> & { page_url: string; } ): Promise<TrackingResponse | null> { return await trackSubmit({ ...eventData, event_name: TrackerEnum.EventName.contact_form_submit, element_selector: eventData.element_selector || TrackerEnum.ElementSelector.contact_form, }); } /** * Track newsletter subscription */ export async function trackNewsletterSubscribe( eventData: Partial<EventData> & { page_url: string; } ): Promise<TrackingResponse | null> { return await trackSubmit({ ...eventData, event_name: TrackerEnum.EventName.newsletter_subscribe, }); } /** * Track modal open */ export async function trackOpenModal( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { return await trackClick({ ...eventData, event_name: TrackerEnum.EventName.open_modal, }); } /** * Track modal close */ export async function trackCloseModal( eventData: Partial<EventData> & { page_url: string; } ): Promise<TrackingResponse | null> { return await trackClick({ ...eventData, event_name: TrackerEnum.EventName.close_modal, element_selector: eventData.element_selector || TrackerEnum.ElementSelector.modal_close, }); } /** * Track product view */ export async function trackViewProduct( eventData: Partial<EventData> & { page_url: string; properties?: Record<string, string>; } ): Promise<TrackingResponse | null> { return await trackPageView({ ...eventData, event_name: TrackerEnum.EventName.view_product, page_title: eventData.page_title || TrackerEnum.PageTitle.product_detail, }); } /** * Track link click */ export async function trackLinkClick( eventData: Partial<EventData> & { page_url: string; element_selector?: string; } ): Promise<TrackingResponse | null> { return await trackClick({ ...eventData, event_name: TrackerEnum.EventName.link_click, element_selector: eventData.element_selector || TrackerEnum.ElementSelector.profile_link, }); } /** * Track copy link action */ export async function trackCopyLink( eventData: Partial<EventData> & { page_url: string; } ): Promise<TrackingResponse | null> { return await trackClick({ ...eventData, event_name: TrackerEnum.EventName.copy_link, }); } // ===== BACKWARD COMPATIBILITY ===== // Các hàm cũ cho backward compatibility /** * Track custom event using global tracker (Deprecated - use specific event functions above) * @deprecated Use specific event type functions instead */ export async function trackCustomEvent( eventType: string, pageUrl: string, sessionId?: string, metadata?: Record<string, any> ): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; return await tracker.trackCustomEvent( eventType, pageUrl, sessionId, metadata ); } /** * Flush pending events using global tracker */ export async function flush(): Promise<TrackingResponse | null> { const tracker = getTracker(); if (!tracker) return null; return await tracker.flush(); } // Export main classes and types export { TrackingAPI } from "./tracking-api"; export { CustomerClient } from "./customer-client"; export { WebsiteClient } from "./website-client"; export { APIKeyClient } from "./apikey-client"; export { TrackingClient } from "./tracking-client"; export { UserClient } from "./user-client"; export { AnalyticsClient } from "./analytics-client"; export { TrackerEnum } from "./tracker.enum"; export { EventData, TrackingResponse, TrackerOptions } from "./types"; // Export all types export * from "./types";