Documentation
Quick Start
Get events flowing in under 5 minutes.
1. Sign up and get your API key
Go to the dashboard, create an account, and generate an API key.
2. Send a test event
curl -X POST https://crosstrack.onrender.com/v1/events \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"anonymousId": "test-visitor-001",
"type": "page_view",
"properties": {"url": "/hello"}
}'
If you get a 201 Created response with a profileId, you're connected.
3. Integrate an SDK
Pick your platform below and follow the guide.
Web SDK
Install
<script src="https://app.crosstrackdata.com/crosstrack.js"></script>
Initialize
CrossTrack.init({
apiKey: 'YOUR_API_KEY',
collectionUrl: 'https://crosstrack.onrender.com'
});
CrossTrack.consent('opted_in');
Track events
// Page view (automatic if autoPageView is true)
CrossTrack.page();
// Custom event
CrossTrack.track('button_click', { button: 'signup', page: '/pricing' });
Identify users
// When a user logs in
CrossTrack.identify('user_123', {
email_hash: 'sha256_of_email'
});
Configuration options
| Option | Default | Description |
|---|---|---|
apiKey | required | Your API key from the dashboard |
collectionUrl | required | CrossTrack backend URL |
autoPageView | true | Automatically track page views |
flushIntervalMs | 30000 | How often to send batched events (ms) |
maxQueueSize | 500 | Max events to queue before dropping oldest |
Methods
| Method | Description |
|---|---|
CrossTrack.init(config) | Initialize the SDK |
CrossTrack.consent(state) | Set consent: 'opted_in', 'opted_out', or 'not_set' |
CrossTrack.track(type, props) | Track a custom event |
CrossTrack.page(props) | Track a page view |
CrossTrack.identify(userId, traits) | Link anonymous session to a known user |
CrossTrack.flush() | Flush event queue immediately |
CrossTrack.reset() | Clear user state and visitor ID |
CrossTrack.getVisitorId() | Get the current visitor ID |
CrossTrack.shutdown() | Stop tracking and flush remaining events |
Android SDK
Install
Add JitPack to settings.gradle.kts:
dependencyResolutionManagement {
repositories {
maven { url = uri("https://jitpack.io") }
}
}
Add the dependency to build.gradle.kts:
implementation("com.github.CrossTrackData:crosstrack-android:0.1.0")
Initialize
// In your Application class
CrossTrack.init(
context = applicationContext,
config = CrossTrackConfig(
apiKey = "YOUR_API_KEY",
collectionUrl = "https://crosstrack.onrender.com"
)
)
CrossTrack.consent().setConsent(ConsentState.OPTED_IN)
Track events
CrossTrack.api().track("screen_view", mapOf("screen" to "home"))
CrossTrack.api().screen("checkout")
Identify users
CrossTrack.api().identify("user_123")
WebView bridge
// Automatically bridges app and WebView identity
webView.webViewClient = CrossTrackWebViewClient(webView)
iOS SDK
Install
In Xcode: File → Add Package Dependencies → paste:
https://github.com/CrossTrackData/crosstrack-ios
Initialize
CrossTrack.shared.initialize(
config: CrossTrackConfig(
apiKey: "YOUR_API_KEY",
collectionUrl: "https://crosstrack.onrender.com"
)
)
CrossTrack.shared.consent().optIn()
Track events
CrossTrack.shared.track("screen_view", properties: ["screen": "home"])
Identify users
CrossTrack.shared.identify("user_123", traits: ["email_hash": "sha256..."])
WebView bridge
CrossTrack.shared.installBridge(on: myWebView)
API Reference
All endpoints require the X-API-Key header.
POST /v1/events
Send a single event.
{
"anonymousId": "visitor-abc",
"type": "page_view",
"properties": { "url": "/pricing" },
"context": {
"platform": "web",
"sessionId": "sess-123"
}
}
POST /v1/events/batch
Send multiple events at once.
{
"events": [
{ "anonymousId": "visitor-abc", "type": "page_view", "properties": {} },
{ "anonymousId": "visitor-abc", "type": "button_click", "properties": {} }
]
}
POST /v1/identify
Link an anonymous session to a known user. Triggers profile merge if the userId is already associated with a different profile.
{
"anonymousId": "visitor-abc",
"userId": "john",
"traits": { "email_hash": "sha256_of_email" }
}
GET /v1/events
Query events. Parameters: since (ISO timestamp, required), limit (default 100, max 1000).
GET /v1/events?since=2026-01-01T00:00:00Z&limit=50
GET /v1/profiles
List profiles updated since a given timestamp. Parameters: since (ISO timestamp, required), limit (default 100, max 1000).
GET /v1/profiles?since=2026-01-01T00:00:00Z&limit=100
GET /v1/profiles/{id}
Get a profile by its profile ID.
GET /v1/profiles/lookup
Look up a profile by any identifier. Parameters: type (VISITOR_ID, USER_ID, EMAIL_HASH, PHONE_HASH), value.
GET /v1/profiles/lookup?type=USER_ID&value=john
Getting Your Data Out
CrossTrack resolves identity — your warehouse, BI tool, or backend is where you analyze it. Here's how to pull resolved data.
Poll resolved events
Fetch events with resolved profileId attached. Poll on a schedule (e.g. every 5 minutes) and load into your warehouse.
curl https://crosstrack.onrender.com/v1/events?since=2026-04-01T00:00:00Z&limit=1000 \
-H "X-API-Key: YOUR_API_KEY"
Each event includes the unified profileId — so even if the original event came from an anonymous session, you get the resolved identity.
Sync all profiles
Fetch profiles updated since a given timestamp. Use this to sync resolved profiles into your warehouse on a schedule.
curl "https://crosstrack.onrender.com/v1/profiles?since=2026-04-01T00:00:00Z&limit=1000" \
-H "X-API-Key: YOUR_API_KEY"
Returns all profiles with their linked user IDs, anonymous IDs, email hashes, and traits. Paginate by advancing the since parameter to the lastSeen of the last profile returned.
Look up a single profile
Query a full profile by user ID, visitor ID, or email hash. Useful for enriching your CRM or personalizing in real-time.
# By user ID
curl "https://crosstrack.onrender.com/v1/profiles/lookup?type=USER_ID&value=john" \
-H "X-API-Key: YOUR_API_KEY"
# By anonymous visitor ID
curl "https://crosstrack.onrender.com/v1/profiles/lookup?type=VISITOR_ID&value=cb221dda-..." \
-H "X-API-Key: YOUR_API_KEY"
Returns the full profile: all linked user IDs, anonymous IDs, email hashes, traits, and event history.
Coming soon
Webhook push and warehouse connectors (BigQuery, Snowflake) are on the roadmap. Vote for what you need — it directly affects what we build next.
How Identity Resolution Works
CrossTrack maintains an identity graph that links anonymous visitor IDs to known user identities.
Profile creation
When a new anonymousId is seen for the first time, a new profile is created.
Login merge
When you call identify(userId), CrossTrack links the anonymousId to the userId. If that userId already belongs to a different profile, the two profiles are merged — all historical events from both profiles are unified under a single profileId.
WebView bridge
When a user opens a WebView inside your app, the native SDK injects the app's visitor ID into the WebView's localStorage. The Web SDK reads it and sends it as context.bridgeId. The server links both IDs to the same profile — no login required.
Deterministic matching
Profiles are merged when they share any of these identifiers:
- User ID — same userId on different anonymous sessions
- Email hash — same hashed email across platforms
- Phone hash — same hashed phone number
- Bridge ID — WebView bridge linking app and web
Troubleshooting
Getting 401 Unauthorized
Check that your X-API-Key header is set correctly. Copy the key from your dashboard — it starts with ct_live_.
Events not showing in dashboard
- Make sure consent is set to
opted_inbefore tracking - Call
flush()to send events immediately (otherwise they batch every 30s) - Check browser console for network errors
Profiles not merging
Profiles only merge when they share an identifier. Make sure identify() is called with the same userId on both platforms.
WebView bridge not working
- Ensure consent is
opted_inbefore the WebView loads - The bridge key in localStorage is
crosstrack_device_id - Check that the domain is in the allowlist (if configured)
Slow first request
On the free tier, the backend sleeps after 15 minutes of inactivity. The first request takes ~30 seconds to wake up. Subsequent requests are fast.
Coming Soon
These features are on our roadmap. Vote for what matters most to you.
Direct delivery to BigQuery, Snowflake, and Redshift.
Push resolved events to your endpoint in real-time.
Add identity resolution on top of your existing Segment pipeline.
Query a user's full resolved profile for personalization.
IP + device fingerprinting with confidence scores.
Cross-platform mobile SDK support.
Have a different request? Tell us what you need.