Documentation Index Fetch the complete documentation index at: https://docs.cryptique.io/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide covers implementation patterns for common Web3 analytics scenarios. Use these patterns to ensure comprehensive, accurate tracking.
Implementation Workflow
Plan Your Events
Define what you want to measure before writing code
Install SDK
Add Cryptique to your application
Configure Auto-Events
Enable/disable automatic tracking
Add Custom Events
Track business-specific actions
Set Up Identification
Link users across sessions
Integrate Wallets
Connect wallet events to user profiles
Verify & Iterate
Test tracking and refine
Common Patterns
Authentication Flow
Track the complete auth journey:
// Signup started
Cryptique . track ( 'signup_started' , {
signup_method: 'email' , // or 'google', 'wallet'
referral_source: getReferralSource ()
});
// Signup completed
Cryptique . track ( 'signup_completed' , {
signup_method: 'email' ,
time_to_complete_seconds: 45
});
// Identify the user
Cryptique . identify ( user . id );
// Set user properties
Cryptique . people . set ({
email: user . email ,
name: user . name ,
signup_date: new Date (). toISOString (),
signup_method: 'email'
});
// Set persistent properties
Cryptique . people . set_once ({
first_seen: new Date (). toISOString (),
original_referrer: document . referrer
});
Wallet Connection Flow
Track wallet interactions:
// Wallet connection initiated
Cryptique . track ( 'wallet_connect_initiated' , {
wallet_type: 'metamask' ,
trigger_location: 'navbar' // or 'modal', 'onboarding'
});
// Wallet connected successfully
async function onWalletConnected ( address , provider ) {
// Track with SDK
Cryptique . walletAddress ( address );
Cryptique . track ( 'wallet_connected' , {
wallet_type: getWalletType ( provider ),
chain_id: await provider . getChainId ()
});
// Optional: set user properties
Cryptique . people . set ({
primary_wallet: address ,
last_wallet_connect: new Date (). toISOString ()
});
Cryptique . people . increment ({
wallet_connect_count: 1
});
}
// Wallet connection failed
function onWalletError ( error ) {
Cryptique . track ( 'wallet_connect_failed' , {
error_type: error . code ,
error_message: error . message ,
wallet_type: 'metamask'
});
}
// Wallet disconnected
function onWalletDisconnected ( address ) {
Cryptique . track ( 'wallet_disconnected' , { address });
}
// Chain changed
function onChainChanged ( chainId , address ) {
Cryptique . track ( 'chain_changed' , {
new_chain_id: chainId ,
wallet_address: address
});
}
DeFi Swap Flow
Track the complete swap journey:
// Token selected
Cryptique . track ( 'token_selected' , {
token_symbol: 'ETH' ,
token_address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' ,
selection_type: 'input' , // or 'output'
search_query: searchTerm || null
});
// Swap quoted
Cryptique . track ( 'swap_quoted' , {
input_token: 'ETH' ,
output_token: 'USDC' ,
input_amount: 1.5 ,
output_amount: 1485.50 ,
exchange_rate: 990.33 ,
slippage_setting: 0.5 ,
route_provider: 'uniswap'
});
// Swap initiated (user clicked swap)
Cryptique . track ( 'swap_initiated' , {
input_token: 'ETH' ,
output_token: 'USDC' ,
input_amount: 1.5 ,
output_amount_expected: 1485.50 ,
slippage_setting: 0.5
});
// Transaction approval requested
Cryptique . track ( 'transaction_approval_requested' , {
token: 'USDC' ,
spender: '0x...router' ,
amount: 'unlimited' // or specific amount
});
// Swap completed (after on-chain confirmation)
Cryptique . track ( 'swap_completed' , {
input_token: 'ETH' ,
output_token: 'USDC' ,
input_amount: 1.5 ,
output_amount_actual: 1483.20 ,
slippage_actual: 0.15 ,
transaction_hash: txHash ,
gas_used: gasUsed ,
gas_price_gwei: gasPriceGwei
});
// Swap failed
Cryptique . track ( 'swap_failed' , {
input_token: 'ETH' ,
output_token: 'USDC' ,
input_amount: 1.5 ,
error_type: 'slippage_exceeded' , // or 'user_rejected', 'insufficient_gas'
error_message: error . message
});
NFT Mint Flow
// Collection viewed
Cryptique . track ( 'collection_viewed' , {
collection_name: 'Cool Cats' ,
collection_address: '0x...' ,
items_available: 500 ,
price_eth: 0.05
});
// Mint initiated
Cryptique . track ( 'mint_initiated' , {
collection_name: 'Cool Cats' ,
quantity: 2 ,
total_price_eth: 0.10 ,
mint_type: 'public' // or 'whitelist', 'allowlist'
});
// Mint completed
Cryptique . track ( 'mint_completed' , {
collection_name: 'Cool Cats' ,
quantity: 2 ,
token_ids: [ 1234 , 1235 ],
total_price_eth: 0.10 ,
transaction_hash: txHash
});
Onboarding Flow
Track multi-step onboarding:
const ONBOARDING_STEPS = [
'welcome' ,
'connect_wallet' ,
'verify_email' ,
'set_preferences' ,
'first_action'
];
function trackOnboardingStep ( step , additionalProps = {}) {
const stepIndex = ONBOARDING_STEPS . indexOf ( step );
Cryptique . track ( 'onboarding_step_completed' , {
step_name: step ,
step_number: stepIndex + 1 ,
total_steps: ONBOARDING_STEPS . length ,
... additionalProps
});
// Update user property
Cryptique . people . set ({
onboarding_step: step ,
onboarding_progress: Math . round (( stepIndex + 1 ) / ONBOARDING_STEPS . length * 100 )
});
}
// On completion
function completeOnboarding () {
Cryptique . track ( 'onboarding_completed' , {
total_time_seconds: timeSinceStart ,
steps_completed: completedSteps . length ,
skipped_steps: skippedSteps
});
Cryptique . people . set ({
onboarding_completed: true ,
onboarding_completed_date: new Date (). toISOString ()
});
}
Error Tracking
Track errors for debugging:
// Generic error tracking
function trackError ( error , context ) {
Cryptique . track ( 'error_occurred' , {
error_type: error . name ,
error_message: error . message ,
error_code: error . code ,
context: context ,
page: window . location . pathname
});
}
// Transaction error
function trackTransactionError ( error , txDetails ) {
Cryptique . track ( 'transaction_error' , {
error_type: classifyError ( error ),
error_message: error . message ,
transaction_type: txDetails . type ,
chain_id: txDetails . chainId ,
gas_estimate: txDetails . gasEstimate
});
}
// Classify errors for better analysis
function classifyError ( error ) {
if ( error . code === 4001 ) return 'user_rejected' ;
if ( error . code === - 32603 ) return 'internal_error' ;
if ( error . message . includes ( 'insufficient funds' )) return 'insufficient_funds' ;
if ( error . message . includes ( 'gas' )) return 'gas_error' ;
return 'unknown' ;
}
Framework-Specific Patterns
React with Wagmi
import { useAccount , useConnect , useDisconnect } from 'wagmi' ;
import { useEffect } from 'react' ;
function WalletTracker () {
const { address , isConnected , chain } = useAccount ();
const { connect , connectors } = useConnect ();
const { disconnect } = useDisconnect ();
// Track connection state changes
useEffect (() => {
if ( isConnected && address ) {
Cryptique . walletAddress ( address );
Cryptique . track ( 'wallet_connected' , {
chain_id: chain ?. id ,
wallet_type: connectors [ 0 ]?. name || 'unknown'
});
}
}, [ isConnected , address , chain ]);
// Track disconnection
const handleDisconnect = () => {
if ( address ) {
Cryptique . track ( 'wallet_disconnected' , { address });
}
disconnect ();
};
return ( /* ... */ );
}
Next.js App Router
// app/providers.jsx
'use client' ;
import { useEffect } from 'react' ;
import { usePathname , useSearchParams } from 'next/navigation' ;
import Cryptique from 'cryptique-sdk' ;
export function AnalyticsProvider ({ children }) {
const pathname = usePathname ();
const searchParams = useSearchParams ();
// Track page views on route change
useEffect (() => {
// Auto page_view should handle this, but for SPAs:
Cryptique . track ( 'page_view' , {
page_path: pathname ,
query_string: searchParams . toString ()
});
}, [ pathname , searchParams ]);
return children ;
}
Vue 3 Composition API
// composables/useTracking.js
import { watch } from 'vue' ;
import { useRoute } from 'vue-router' ;
import Cryptique from 'cryptique-sdk' ;
export function useTracking () {
const route = useRoute ();
// Track route changes
watch (
() => route . fullPath ,
( newPath ) => {
Cryptique . track ( 'page_view' , {
page_path: newPath
});
}
);
const trackEvent = ( name , properties ) => {
Cryptique . track ( name , properties );
};
return { trackEvent };
}
Groups (companies, teams, workspaces)
Model B2B or multi-tenant context with Groups : assign the user, then set properties on the group profile.
Cryptique . identify ( user . id );
await Cryptique . set_group ( 'company' , user . companyId );
const company = Cryptique . get_group ( 'company' , user . companyId );
await company . set ({
name: user . companyName ,
plan: user . companyPlan
});
Cryptique . track ( 'report_exported' , { format: 'csv' });
Use add_group / remove_group when a user can belong to multiple IDs under the same key. After identify(), the server may return group_memberships to hydrate assignments on a new device.
Testing Your Implementation
Debug Mode
Enable debug logging:
// CDN
script . setAttribute ( 'debug' , 'true' );
// npm
await Cryptique . init ({
siteId: 'YOUR_SITE_ID' ,
debug: true // Logs all events to console
});
Verification Checklist
Check Live Events
Go to Dashboard → Live Events and perform actions
Verify User Profiles
Check that identify() creates/updates profiles
Test Wallet Linking
Connect wallet and verify it appears on profile
Check Properties
Verify all expected properties are present
Test Error Cases
Trigger errors and verify tracking
Common Issues
Check Site ID is correct
Verify domain is allowed in settings
Check for ad blocker interference
Look for console errors
Ensure identify() is called after SDK loads
Verify distinct_id is a string
Check that properties are valid JSON
Call Cryptique.walletAddress() with a valid address
Verify address format (0x…)
Confirm the SDK session initialized (Site ID, domain allowlist)
Check SDK isn’t initialized twice
Verify event handlers aren’t double-bound
Review SPA routing configuration
Next Steps
SDK Reference Full method documentation
Build Reports Analyze your data