A project is your product, not one of its apps
A project holds everything Togo knows about one product: its events and event registry, the people who use it, its write keys and its reporting time zone. It belongs to an organization, and everyone in the organization works on it together.
One product is one project — its marketing site, its web app, its mobile apps, its servers and its integrations together. Togo follows a person across those parts only inside one project. Split them into several projects and each holds a fragment of the same people, with no way to join them afterwards.
| Put in the same project | Give its own project |
|---|---|
| The website, the web app and the mobile apps | A second, separate product |
| Your API servers, background jobs and webhook handlers | A product you build for a client |
| Development, staging and production of all of the above | — |
Environments are not projects. Every project has two kinds of write key: a test key
(togo_pkt_…) for development and staging, whose events appear within seconds and are never
charted, and a live key (togo_pkl_…) for production. Give each part of your system its own
pair of keys inside the project — website, game-server, payments — rather than a project
each.
One userId everywhere
Inside a project, Togo joins a person’s activity by your id for them: the userId the browser
passes to identify() and your servers pass on every call. So the rule is short:
Every part of your system uses the same userId for the same person — your own account id,
the one your database already holds.
- Not an email address, and not a username a person can change.
- Not a platform’s own id — an app store, console or social login id. Map it to your account id first, and send that.
- Never invented for a guest. A visitor or player who has not signed in is anonymous, and that
is fine: their activity on the device joins their account the moment the app calls
identify(). Do not make up auserIdto fill the gap.
Different ids in different places split one person into several, and every count of people, every funnel and every retention curve is quietly wrong. People and identity explains how Togo decides who is who.
Example: a game on the web, on phones and on your servers
Take a game that people discover on its website, play on their phones, and pay for through an app
store, with your game server and a payments webhook behind it. Four parts, one project, one
userId — the player’s account id.
1. The website — sign-up. The browser SDK records the visit and the sign-up, and identify()
joins the visitor’s anonymous browsing to their new account:
// website
const analytics = init({
writeKey: process.env.NEXT_PUBLIC_TOGO_WRITE_KEY!,
defaultProperties: { platform: 'web' },
});
analytics.track('account_created', { referral: 'friend_invite' });
analytics.identify(account.id);
2. The mobile game — logging in and playing. The mobile SDK makes the same calls as the
browser one. When the player logs in on their phone with the account they made on the website,
identify() with the same id joins the phone to that player — including anything they did in
the app before logging in:
// iOS app
Togo.setup(TogoConfig(writeKey: "togo_pkl_…", defaultProperties: ["platform": "ios"]))
Togo.identify(account.id) // after login: the same id the website used
Togo.track("level_completed", properties: ["level": 12])
Your game server records what happens on its side — a match result, a reward granted — with the same id:
// game server
const analytics = init({
writeKey: process.env.TOGO_WRITE_KEY!,
defaultProperties: { service: 'game-server' },
});
analytics.track('match_won', { mode: 'ranked' }, { userId: account.id });
3. The payments webhook — revenue. When the store confirms a purchase, record it with the same id:
// payments webhook
analytics.track('gems_purchased', { pack: 'starter', price_bucket: '1-5' }, { userId: account.id });
await analytics.flush(); // a webhook handler is often serverless
4. One person, one journey. Because every part uses account.id in one project, Togo sees one
player: the website visit and its campaign, the sign-up, the first login on a phone two days
later, the levels, and the first purchase. The platform and service properties still tell the
channels apart whenever you want them apart.
What one view lets you ask
With the whole journey in one project, questions that cross channels have answers. Ask your agent through the Togo MCP server:
Of the players who signed up on the website last month, how many logged in on mobile
within 7 days, and how many of those bought gems?
Of the players who came from a friend invite, how many bought gems within 30 days?
Where between website sign-up and first purchase do most players drop off?
Each of those needs the website, the game and the payments in one place. Across separate projects, the first step of the funnel and the last would belong to different people, and the answer would be missing or wrong.
That single view is what lets an agent help with what matters most — where the experience loses people, which channels bring players who stay, and what leads to a first purchase — instead of answering for one channel at a time.
Setting it up
- With your agent: Install Togo with your AI agent. Its setup looks for this product’s existing project before creating one, and gives each part of your system its own key pair inside it.
- By hand: create one project in app.togohq.ai, then follow the guide
for each part — Next.js, React, Node.js and
serverless, your mobile app — using that project’s keys everywhere, and the same
userId.