posthog-js
Version:
Posthog-js allows you to automatically capture usage and send events to PostHog.
257 lines (251 loc) • 9.09 kB
TypeScript
import { PostHog } from './module';
import { PropertyMatchType, SurveyEventWithFilters, SurveyActionType } from '@posthog/browser-common';
import { SurveyPosition } from '@posthog/core';
declare function elementIsVisible(element: HTMLElement, cache: WeakMap<HTMLElement, boolean>): boolean;
interface SelectorGroup {
cardinality: number;
cssSelectors: Array<{
css: string;
offset: number;
}>;
}
interface AutoData {
notextGroups: SelectorGroup[];
textGroups: SelectorGroup[];
}
interface InferredSelector {
autoData: string;
text: string | null;
excludeText?: boolean;
precision?: number;
}
/**
* if inferSelector is the sauce, this is the nugget
*
* find an element in the dom using the element inference data
*
* 1. try each group of selectors, starting with most specific (lowest cardinality)
* 2. try each selector in the group - run the css query, go to offset
* 3. "vote" for the element if it was found
* 4. return early if any element gets majority votes
* 5. return element w/ most votes
*/
declare function findElement(selector: InferredSelector): HTMLElement | null;
declare function getElementPath(el: HTMLElement | null, depth?: number): string | null;
interface JSONContent {
type?: string;
attrs?: Record<string, any>;
content?: JSONContent[];
marks?: {
type: string;
attrs?: Record<string, any>;
}[];
text?: string;
}
type ProductTourStepType = 'element' | 'modal' | 'survey' | 'banner';
interface ProductTourBannerConfig {
behavior: 'sticky' | 'static' | 'custom';
selector?: string;
action?: {
type: 'none' | 'link' | 'trigger_tour';
link?: string;
tourId?: string;
};
animation?: {
duration?: number;
};
}
/** Button actions available on modal steps */
type ProductTourButtonAction = 'dismiss' | 'link' | 'next_step' | 'previous_step' | 'trigger_tour';
interface ProductTourStepButton {
text: string;
action: ProductTourButtonAction;
/** URL to open when action is 'link' */
link?: string;
/** Tour ID to trigger when action is 'trigger_tour' */
tourId?: string;
}
interface ProductTourStepButtons {
primary?: ProductTourStepButton;
secondary?: ProductTourStepButton;
}
type ProductTourSurveyQuestionType = 'open' | 'rating';
interface ProductTourSurveyQuestion {
type: ProductTourSurveyQuestionType;
questionText: string;
/** Rating display type - emoji or number */
display?: 'emoji' | 'number';
/** Rating scale - 3 or 5 for emoji, 5 or 10 for number */
scale?: 3 | 5 | 10;
/** Label for low end of rating scale (e.g., "Not likely") */
lowerBoundLabel?: string;
/** Label for high end of rating scale (e.g., "Very likely") */
upperBoundLabel?: string;
submitButtonText?: string;
backButtonText?: string;
}
interface ProductTourStep {
id: string;
type: ProductTourStepType;
selector?: string;
progressionTrigger: 'button' | 'click';
content: JSONContent | null;
/** Pre-rendered HTML content from the editor. If present, SDK should use this instead of rendering from JSONContent. */
contentHtml?: string;
/** Inline survey question config - if present, this is a survey step */
survey?: ProductTourSurveyQuestion;
/** ID of the auto-created survey for this step (set by backend) */
linkedSurveyId?: string;
/** ID of the survey question (set by backend, used for event tracking) */
linkedSurveyQuestionId?: string;
/** Enhanced element data for more reliable lookup at runtime */
inferenceData?: InferredSelector;
/** Use CSS selector instead of inference. Defaults to false (use inference). */
useManualSelector?: boolean;
/** Maximum tooltip width in pixels (defaults to 320px) */
maxWidth?: number;
/** Position for modal/survey steps (defaults to middle_center) */
modalPosition?: SurveyPosition;
/** Button configuration for modal steps */
buttons?: ProductTourStepButtons;
/** Banner configuration (only for banner steps) */
bannerConfig?: ProductTourBannerConfig;
/** translation data for this tour step */
translations?: Record<string, ProductTourStepTranslation>;
}
/** all translatable content for a given tour step */
interface ProductTourStepTranslation {
content?: ProductTourStep['content'];
contentHtml?: ProductTourStep['contentHtml'];
buttons?: {
primary?: Pick<ProductTourStepButton, 'text'>;
secondary?: Pick<ProductTourStepButton, 'text'>;
};
survey?: Pick<ProductTourSurveyQuestion, 'questionText' | 'lowerBoundLabel' | 'upperBoundLabel' | 'submitButtonText' | 'backButtonText'>;
}
/** maps to main repo EffectiveProductTourType */
type ProductTourType = 'tour' | 'announcement' | 'banner';
interface ProductTourWaitPeriod {
days: number;
types: ProductTourType[];
}
interface ProductTourConditions {
url?: string;
urlMatchType?: PropertyMatchType;
selector?: string;
autoShowDelaySeconds?: number;
events?: {
values: SurveyEventWithFilters[];
} | null;
cancelEvents?: {
values: SurveyEventWithFilters[];
} | null;
actions?: {
values: SurveyActionType[];
} | null;
linkedFlagVariant?: string;
deviceTypes?: string[];
seenTourWaitPeriod?: ProductTourWaitPeriod;
}
interface ProductTourAppearance {
backgroundColor?: string;
textColor?: string;
buttonColor?: string;
borderRadius?: number;
buttonBorderRadius?: number;
borderColor?: string;
fontFamily?: string;
boxShadow?: string;
showOverlay?: boolean;
whiteLabel?: boolean;
/** defaults to true, auto-set to false for announcements/banners */
dismissOnClickOutside?: boolean;
zIndex?: number;
}
type ProductTourDisplayFrequency = 'show_once' | 'until_interacted' | 'always';
interface ProductTour {
id: string;
name: string;
description?: string;
tour_type: ProductTourType;
auto_launch?: boolean;
start_date: string | null;
end_date: string | null;
current_iteration?: number;
conditions?: ProductTourConditions;
appearance?: ProductTourAppearance;
steps: ProductTourStep[];
internal_targeting_flag_key?: string;
linked_flag_key?: string;
display_frequency?: ProductTourDisplayFrequency;
disable_image_preload?: boolean;
}
type ProductTourCallback = (tours: ProductTour[], context?: {
isLoaded: boolean;
error?: string;
}) => void;
type ProductTourDismissReason = 'user_clicked_skip' | 'user_clicked_outside' | 'escape_key' | 'element_unavailable' | 'container_unavailable';
type ProductTourRenderReason = 'auto' | 'api' | 'trigger' | 'event';
interface ShowTourOptions {
reason?: ProductTourRenderReason;
enableStrictValidation?: boolean;
}
declare class ProductTourManager {
private _instance;
private _activeTour;
private _currentStepIndex;
private _isPreviewMode;
private _isResuming;
private _checkInterval;
private _triggerSelectorListeners;
private _pendingTourTimeouts;
private _eventReceiver;
private _registeredEventTourIds;
private _preloadedImageUrls;
constructor(instance: PostHog);
private _preloadTourImages;
private _getCurrentStep;
private _setStepIndex;
private _saveSessionState;
private _clearSessionState;
private _getSessionState;
start(): void;
private _startEvaluationLoop;
private _resumeSavedTour;
stop(): void;
private _handleVisibilityChange;
private _evaluateAndDisplayTours;
private _showOrQueueTour;
private _isTourEligible;
showTour(tour: ProductTour, options?: ShowTourOptions): boolean;
showTourById(tourId: string, reason?: ProductTourRenderReason): void;
previewTour(tour: ProductTour): void;
nextStep: () => void;
previousStep: () => void;
dismissTour: (reason?: ProductTourDismissReason) => void;
private _handleBannerActionClick;
private _handleButtonClick;
private _completeTour;
private _renderCurrentStep;
private _renderTooltipWithPreact;
private _renderBanner;
private _renderSurveyStep;
private _isProductToursFeatureFlagEnabled;
private _cleanup;
private _manageTriggerSelectorListener;
private _removeTriggerSelectorListener;
private _removeAllTriggerListeners;
private _captureEvent;
private _captureStepShown;
private _captureStepSelectorFailed;
getActiveProductTours(callback: ProductTourCallback): void;
resetTour(tourId: string): void;
resetAllTours(): void;
cancelPendingTour(tourId: string): void;
private _cancelAllPendingTours;
isTourPending(tourId: string): boolean;
queueTourWithDelay(tourId: string, delaySeconds: number, reason?: ProductTourRenderReason): void;
}
declare function generateProductTours(posthog: PostHog, isEnabled: boolean): ProductTourManager | undefined;
export { generateProductTours as default, elementIsVisible, findElement, getElementPath };
export type { AutoData, InferredSelector, SelectorGroup };