Get started
Quickstart: from sign-up to your first attributed customer
Create a workspace, connect billing and search, install the snippet and call identify(). What appears the same day, and what needs new customers first.
This page takes you from a new account to the first customer Joinsight can credit to a page. Most of it takes one sitting. The part you can't speed up is waiting for new customers to arrive after the snippet is live, so the page also says what you can read on day one and what fills in over the following weeks.
You'll need:
- A Stripe account you can create a restricted key in, or a RevenueCat project you can create an API v2 secret key in. Either one is enough.
- A Google account with access to your Search Console property. If you use GA4 or Plausible, access to that too.
- Access to your site's HTML, your signup code and the code that creates Stripe Checkout sessions. This is only needed for attribution, which is optional.
Create your account and a workspace
Sign in with your email. Joinsight sends a link and a 6-digit code; there is no password. If "Continue with Google" is offered, that works too, and both reach the same account because accounts are keyed by email. Signing in for the first time creates the account.
Then create a workspace. A workspace is one product: its billing, its search property and its site. The form asks for three things:
| Field | What it does |
|---|---|
| Workspace name | Usually your product's name. |
| Reporting currency | EUR, USD, GBP, CHF, CAD or AUD. Every amount is converted to it with daily ECB reference rates. |
| Time zone | Prefilled from your browser. The Monday brief arrives at 08:00 in this time zone. |
You can change all three later in Settings. The time zone has to be an IANA name, such as Europe/Paris.
Creating the workspace shows its secret key once, with a copy button. Your server only needs it if you call identify() from your backend; Joinsight keeps a hash, so copy it now or rotate a new one later in Settings → Keys. Continue to setup then opens the Setup page.
The setup checklist
Setup lists five steps. Each one shows its state: done, waiting (connected and importing), optional, or skipped. The page counts them as "N of 5 steps done" and refreshes on its own while a step is waiting.
| Step | Required | What it unlocks |
|---|---|---|
| 1. Connect a revenue source | Yes | MRR, movements, customers, one-time sales and their history |
| 2. Add mobile: RevenueCat and App Store Connect | No, skip it if you only sell on the web | Mobile MRR and trials, store page views and downloads by source |
| 3. Connect Search Console | Yes | Clicks, impressions and positions by page and query. The step is done once a Search Console property syncs; GA4 or Plausible is optional and adds sessions by landing page |
| 4. Install the snippet | No, you can skip it | The first touch of each visitor: the basis of page, channel and keyword revenue |
| 5. Link payments to signups | No, you can skip it | Each new customer credited to the page and channel that first brought them |
Until your workspace has revenue, the Overview screen shows the same steps, minus the mobile one, under "Get your first answer", with the step to do next highlighted. Once billing has imported a payment, or once every step is done or skipped, the Overview becomes the dashboard.
Step 1: connect billing
Joinsight reads billing data and never writes to it.
Stripe. Paste a restricted key; secret keys and publishable keys are refused. The Stripe card has a link that opens Stripe's key form with the right Read permissions already ticked, so check them and create the key. Keys starting with rk_live_ connect your live data and keys starting with rk_test_ connect test mode. The list includes Charges, which covers sales outside subscriptions, such as Checkout in payment mode and Payment Links. A key without it still connects, but those one-time sales are left out until you add it.
RevenueCat. Paste an API v2 secret key and your project ID, then add the webhook URL and Authorization header shown on the card to RevenueCat's webhook settings, so renewals and cancellations arrive as they happen.
The backfill starts right away and its progress shows on the card. Every subscription is imported, not only the ones created after you connected, so the MRR chart covers your whole history. The exact permissions, sync frequency and how a subscription visible in both Stripe and RevenueCat is counted once are on Connect Stripe and RevenueCat.
Connecting Stripe or RevenueCat starts your 14-day trial clock. Signing up and creating a workspace don't. See The trial below.
Step 2: add mobile sources
Skip this if you only sell on the web. If you sell in an app, connect RevenueCat (if you didn't in step 1) and App Store Connect. App Store data arrives 1–2 days after connecting. Details are on Connect App Store Connect and Instagram.
Step 3: connect Search Console and traffic
Sign in with Google, then pick your Search Console property and select Save and sync. Until a property is saved, the Google card shows Setup not finished and nothing imports. In the same form, choose a traffic source: GA4 (then pick the property), Plausible, or None. Plausible connects separately, with a Stats API key on its own card, and only one of the two can be the traffic source. With None, the snippet still counts visitors per page.
Search Console keeps 16 months of performance data, and Joinsight imports all of it on the day you connect. That is why keyword and page click data is useful before the snippet has recorded anything. GA4 is backfilled 13 months and Plausible 12 months. Search Console data runs 2–3 days behind, which is Google's delay, not a sync problem. More on Connect Search Console, GA4 or Plausible.
Step 4: install the snippet
The snippet is a small first-party script, under 2 KB. It records where each visitor first landed: the landing page, the referring domain, UTM tags and ad click IDs. Copy the exact tag from the Setup page, because it carries your workspace's public site key:
<script>window.joinsight=window.joinsight||function(){(joinsight.q=joinsight.q||[]).push(arguments)}</script>
<script defer src="…/j.js" data-site="js_site_…"></script>
The snippet stores nothing until it has consent. Call this from your cookie banner:
joinsight("consent", true); // accepted
joinsight("consent", false); // refused or withdrawn
If consent is handled elsewhere, or doesn't apply to you, add data-consent="granted" to the script tag instead.
After deploying, open your site in a new private window by typing its address, and accept your banner on that first page. Only a landing page starts a session: a page reached through a link on your own site doesn't. The "Last session" check on the Setup page turns green on the first event. Serving the script from your own domain, so ad blockers don't drop it, is covered on Install the tracking snippet.
Step 5: link payments to signups
This step is what turns a visit into a credited customer. It takes two small changes.
Call identify() once, right after signup succeeds, with your own user ID and the email:
joinsight("identify", user.id, user.email);
This links the visitor's anonymous ID to your user ID. The email is hashed on arrival and only used as a fallback match. You can also identify from your server with the workspace's secret key; see Link visitors to customers with identify().
Put the same user ID on the Stripe subscription. Stripe doesn't copy Checkout Session metadata to the subscription or customer, so set it with subscription_data.metadata:
// Stripe Checkout: tag the customer and subscription with your user ID
const session = await stripe.checkout.sessions.create({
mode: "subscription",
line_items: [{ price: priceId, quantity: 1 }],
client_reference_id: user.id,
customer_email: user.email,
subscription_data: { metadata: { user_id: user.id } },
success_url: "https://yourapp.com/welcome",
});
// For existing customers: stripe.customers.update(id, { metadata: { user_id: user.id } })
Joinsight reads metadata.user_id from the Stripe customer, and from the subscription when the customer has none. For RevenueCat, use the same user ID as the app user ID; anonymous RevenueCat IDs are ignored. When no user ID matches, Joinsight falls back to the hashed email, which only works if the person paid with the email they signed up with. The reasons for each placement are in Stripe Checkout metadata and the user ID.
Then check it end to end. Sign up on your site as a new visitor, then pay. How depends on what is connected, and the Setup step says which applies:
- A test-mode Stripe key: pay with a test card.
- A live Stripe key: test payments never reach it, so subscribe with a real card on your cheapest plan. You can refund it in Stripe afterwards, but cancel at the end of the period rather than immediately, so it still counts as paid. Your next real customer who signs up after the snippet went live works just as well.
- RevenueCat only: sandbox purchases are left out, so subscribe for real with the account you just created.
The Setup step first shows "identify() works" with the number of signups it has seen, then "Ready" once a paying customer links to their first visit. Linking runs about two minutes after an identify() call and again after billing syncs, so give it a few minutes.
What appears when
Joinsight is useful on day one, but attribution is only as good as the number of customers who arrived after the snippet went live.
| When | What you see |
|---|---|
| Minutes after connecting billing | Combined MRR and its full history, net new MRR and the movements behind it, active subscribers, trial conversion, churn, one-time sales, at-risk MRR on past-due subscriptions |
| The day you connect Google | 16 months of Search Console clicks, impressions and positions by page and query, plus GA4 or Plausible traffic |
| 1–2 days after connecting App Store Connect | Store impressions, product page views and downloads by source |
| From the first consented visit | Sessions by landing page and channel |
| From the first customer who visits, signs up and pays after the snippet and identify() are live | That customer's first page and channel, and the first attributed MRR |
| About 30 days after the snippet goes live | Page, channel and keyword revenue reliable enough to act on, and keyword opportunities, which rank queries on pages that already earn |
While the snippet is younger than 30 days, the Overview shows "Attribution warming up: day N of 30" with a progress bar. Customers who signed up before the snippet and identify() were live have no first touch and stay unattributed; that history isn't recoverable. How the numbers are built is on How attribution works.
Skipping the optional steps
Attribution is opt-in. If you only want combined MRR and search data, skip the snippet and linking steps with "Skip" on the Setup page or the Overview checklist. A skipped step is remembered for everyone in the workspace, and "Undo" brings it back. Skipping the snippet also skips linking, because linking needs the snippet.
Once the steps are done or skipped, the Overview shows the dashboard even before a payment arrives. Its page panel then says attribution is off, with a link back to Setup, and the trial emails don't ask you to install what you skipped.
The trial
The trial gives you 14 days with every feature and no card required.
- The clock starts when your first revenue source connects, not at sign-up. Exploring the sample workspace doesn't start it.
- Day 2 to 4: if the snippet hasn't sent an event, or identify() hasn't been called yet, you get one email with the exact missing step and an offer to set it up together on a short call. Skipped steps don't trigger it.
- Day 12: an email with what Joinsight found so far: new paying customers, how many were attributed, and your top page if one has earned.
- Day 14: if fewer than 5 new paying customers were matched to a first touch during the trial, the trial is extended once by another 14 days, and you get an email saying so. Fewer matches than that is too few to judge which pages make money, and the 30-day attribution warm-up is longer than the trial anyway.
The days left show at the bottom of the sidebar, with a link to choose a plan. Plans are on pricing, and billing is covered in Workspaces, team, settings and billing.
Explore with sample data
While your own workspace is still empty, the Overview offers "Create a sample workspace", and the workspace switcher offers it at any time when you don't have one. It builds a separate workspace for a fictional app with 16 months of revenue, search, App Store and Instagram data. It takes about 20 seconds and leaves your workspace untouched.
The sample workspace is marked "sample data" in the workspace switcher, doesn't count toward your plan's workspace limit, and doesn't sync: its connections are read-only. It's a quick way to see what each screen looks like with months of history before your own attribution has warmed up.
Next steps
- Read the dashboard: what each screen answers.
- How attribution works: what is measured, what is modeled, and why the attributed share is below 100%.
- Use Joinsight in your AI assistant: ask the same numbers from your AI assistant.