Relay is a privacy-focused deferred linking solution that helps you track referrals and attribute users without relying on third-party analytics services. Built for React Native and Expo applications, it gives you complete control over your user attribution data.
The Problem: Traditional referral tracking requires complex analytics SDKs, sends data to third parties, and often violates user privacy. Cookie-based solutions don't work in mobile apps, and deep links alone can't bridge the gap between initial visit and user signup.
The Solution: Relay uses device fingerprinting to create a privacy-preserving bridge between when a user first visits your app (via a referral link) and when they complete signup. All data stays on your infrastructure, giving you full compliance control and zero external dependencies.
No third-party tracking services. Your user data stays on your infrastructure. Full GDPR/CCPA compliance control.
Works with any storage solution: JSON files, PostgreSQL, MongoDB, Redis, or your custom database. You control where and how data is stored.
Two-phase flow: capture fingerprints on referral visit, process attribution on signup. Just two API calls to implement.
Track referrals, measure marketing campaigns, implement deep linking, or build custom attribution logic with hooks.
No analytics SDKs, no tracking pixels, no external services. Just your app and your server.
# Using npm
npm install @korsolutions/relay
# Using pnpm
pnpm add @korsolutions/relay
# Using yarn
yarn add @korsolutions/relayimport { RelayExpoClient } from "@korsolutions/relay";
const client = new RelayExpoClient({
serverUrl: "https://api.yourdomain.com",
});
// Capture fingerprint when user visits referral link
await client.capture({
referralCode: "FRIEND123",
});
// Process attribution after user signs up
const result = await client.process({
userId: "user_12345",
});
if (result.referralCode) {
// Reward the referrer!
console.log(`Referred by: ${result.referralCode}`);
}import { createRelayServer } from "@korsolutions/relay/server";
const relay = createRelayServer({
fingerprint: {
methods: {
storeFingerprint: async (fingerprint, hash) => {
// Save to your database
return await db.fingerprints.create({ fingerprint, hash });
},
getFingerprintByHash: async (hash) => {
// Retrieve from your database
return await db.fingerprints.findOne({ hash });
},
},
},
deferredLink: {
methods: {
storeDeferredLink: async (link) => {
await db.deferredLinks.create(link);
},
getDeferredLinkByFingerprintHash: async (hash) => {
return await db.deferredLinks.findOne({ fingerprintHash: hash });
},
deleteDeferredLink: async (id) => {
await db.deferredLinks.delete(id);
},
},
},
hooks: {
onMatchFound: async (deferredLink, authCtx) => {
// React to successful matches with access to authenticated user
if (authCtx?.userId) {
// Award referral points, send notifications, etc.
await rewardReferral(authCtx.userId, deferredLink);
}
},
},
});
// Handler with auth context
app.post("/api/relay/*", async (req, res) => {
const user = await getUserFromSession(req);
const request = new Request(req.url, {
method: req.method,
body: JSON.stringify(req.body),
});
const response = await relay.handler(request, {
userId: user?.id ?? null,
});
res.status(response.status).json(await response.json());
});Relay uses a two-phase attribution flow:
When a user clicks a referral link and opens your app:
- Generate anonymous device fingerprint (locale, timezone, device info)
- Send fingerprint + referral data to your server
- Store the association in your database
When the user completes signup:
- Generate the same fingerprint
- Match against stored fingerprints
- Attribute the referral and trigger rewards
Privacy Note: Fingerprints use non-personal device characteristics (locale, timezone, screen dimensions). No PII is collected.
- Referral Programs - Track who referred whom, reward users accurately
- Marketing Attribution - Measure campaign effectiveness across web-to-app transitions
- Deep Linking - Preserve context when users move from browser to native app
- Growth Analytics - Understand acquisition funnels without third-party tracking
- Device Fingerprinting - Anonymous, privacy-preserving identification
- Authentication Context - Pass user information to hooks for immediate referral attribution
- Flexible Storage - Bring your own database or use built-in adapters
- Server Hooks - Customize behavior at capture and process stages with access to authenticated user data
- Type Safety - Full TypeScript support with Zod validation
- Expo Compatible - Built specifically for Expo and React Native
- Self-Hosted - Complete control over your infrastructure
- Zero Dependencies - No external services or tracking SDKs
Visit korsoftwaresolutions.github.io/relay for full documentation:
Check out the examples directory for complete implementations:
- Expo Example - Full referral flow with capture and process screens
- Server Examples - JSON storage, PostgreSQL, and MongoDB implementations
Contributions are welcome! Please read our contributing guidelines before submitting a PR.
If you discover a security vulnerability, please email contact@korsolutions.net. Do not open public issues for security concerns.
Relay is released under the O'Saasy License.
Relay is built and maintained by Kor Solutions.