@tracetail/react
Version:
React hooks for TraceTail enterprise browser fingerprinting with over 99.5% accuracy. TypeScript support and React 18 compatibility.
153 lines (150 loc) • 4.67 kB
JavaScript
import { jsx, Fragment } from 'react/jsx-runtime';
import { useState, useRef, useEffect, useCallback } from 'react';
import { TraceTail } from '@tracetail/js';
export { TraceTail } from '@tracetail/js';
/**
* React hook for basic browser fingerprinting
*
* @example
* ```typescript
* import { useTraceTail } from '@tracetail/react';
*
* function MyComponent() {
* const { fingerprint, loading, error } = useTraceTail({
* apiKey: 'your-api-key',
* immediate: true
* });
*
* if (loading) return <div>Generating fingerprint...</div>;
* if (error) return <div>Error: {error.message}</div>;
*
* return <div>Visitor ID: {fingerprint?.visitorId}</div>;
* }
* ```
*/
function useTraceTail(options) {
const [fingerprint, setFingerprint] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const traceTailRef = useRef(null);
// Initialize TraceTail instance
useEffect(() => {
if (!traceTailRef.current) {
traceTailRef.current = new TraceTail(options);
}
}, [options.apiKey, options.endpoint]);
const generate = useCallback(async () => {
if (!traceTailRef.current) {
throw new Error('TraceTail not initialized');
}
setLoading(true);
setError(null);
try {
const result = await traceTailRef.current.generateFingerprint({
verbose: true
});
setFingerprint(result);
return result;
}
catch (err) {
const error = err instanceof Error ? err : new Error('Unknown error');
setError(error);
throw error;
}
finally {
setLoading(false);
}
}, []);
const regenerate = useCallback(async () => {
setFingerprint(null);
return generate();
}, [generate]);
// Auto-generate on mount if immediate is true
useEffect(() => {
if (options.immediate && !fingerprint && !loading) {
generate().catch(() => {
// Error is already handled in generate function
});
}
}, [options.immediate, fingerprint, loading, generate]);
return {
fingerprint,
loading,
error,
generate,
regenerate
};
}
/**
* React hook for visitor identification with persistent storage
*
* @example
* ```typescript
* import { useVisitorId } from '@tracetail/react';
*
* function UserTrackingComponent() {
* const { visitorId, isReturningVisitor, loading } = useVisitorId({
* apiKey: 'your-api-key',
* storageKey: 'app_visitor_id'
* });
*
* return (
* <div>
* <p>Visitor: {visitorId}</p>
* <p>Status: {isReturningVisitor ? 'Returning' : 'New'} visitor</p>
* </div>
* );
* }
* ```
*/
function useVisitorId(options) {
const storageKey = options.storageKey || 'tracetail_visitor_id';
const [visitorId, setVisitorId] = useState(null);
const [isReturningVisitor, setIsReturningVisitor] = useState(false);
const { fingerprint, loading, error, generate } = useTraceTail({
...options,
immediate: true
});
// Update visitor ID when fingerprint changes
useEffect(() => {
if (fingerprint === null || fingerprint === void 0 ? void 0 : fingerprint.visitorId) {
const storedVisitorId = localStorage.getItem(storageKey);
if (storedVisitorId) {
setIsReturningVisitor(storedVisitorId === fingerprint.visitorId);
}
else {
setIsReturningVisitor(false);
}
setVisitorId(fingerprint.visitorId);
localStorage.setItem(storageKey, fingerprint.visitorId);
}
}, [fingerprint === null || fingerprint === void 0 ? void 0 : fingerprint.visitorId, storageKey]);
const refresh = useCallback(async () => {
await generate();
}, [generate]);
return {
visitorId,
isReturningVisitor,
loading,
error,
refresh
};
}
const TraceTailProvider = ({ children }) => {
// This is a simple provider that could be extended with context
// For now, it just renders children since hooks manage their own instances
return jsx(Fragment, { children: children });
};
/**
* Get the current React package version
*/
const getVersion = () => '2.3.4';
// Default export
var index = {
useTraceTail,
useVisitorId,
TraceTailProvider,
getVersion
};
export { TraceTailProvider, index as default, getVersion, useTraceTail, useVisitorId };
//# sourceMappingURL=index.esm.js.map