Next.js and SaaS company

Keeping the widget on the marketing routes and out of the product

A subscription business built in one codebase has a boundary running through it that the framework does not care about: some routes are a website and some routes are the product. The root layout owns both. Putting the tag there is the correct general advice and the wrong specific advice here, because it installs a public assistant into a screen where every visitor is authenticated and every question is about their own account.

Why this pairing is its own job

The Next.js install guide covers the tag, and the SaaS company guide covers what the assistant has to know. What follows is the part that belongs to neither.

  • The root layout wraps every route in the app, so a tag placed there appears on the pricing page and inside the dashboard equally, and nothing about the install makes that visible.
  • A signed in customer who sees a chat launcher assumes it knows who they are. Every question they type is the category the assistant cannot answer, and being refused by something that appeared inside the product reads as a broken feature rather than a scoped tool.
  • Route groups make the fix almost free, which is the argument for doing it before launch rather than after somebody screenshots a refusal.
  • If your product is a separate deployment on its own subdomain, the problem inverts: the boundary is enforced by the deploy, and the question becomes whether you want the assistant to follow customers there at all.

What changes about the install here

<script src="https://cdn.askably.xyz/w.js" data-key="pk_live_YOUR_KEY" defer></script>

The tag is the same one on the Next.js guide. Everything below is about where it goes on a SaaS company site specifically.

Put the tag in the marketing layout, not the root layout

Group your public routes and give that group its own layout, then render the tag as the last child of the body element there. The root layout keeps the html and body elements and nothing else that concerns the widget.

This is a five minute change while there are two layouts and a much larger one after a year of shared providers have accumulated in the root. It is worth doing at install time even if the product half of the app is still small.

Do not try to make it conditional on the session

The tempting shortcut is one layout that renders the tag only when nobody is signed in. It puts a public marketing concern inside the code path that handles authentication, and it moves the tag into something that can re-render as session state resolves.

The loader installs once and ignores a second attempt, so this rarely produces two launchers. What it produces is a launcher that appears for a moment on a dashboard during hydration, and a piece of logic nobody wants to touch later.

Two layouts express the same rule as a routing fact rather than as a runtime condition, and routing facts are the ones you can verify by opening a URL.

Decide where the documentation route belongs

Plenty of subscription products serve their docs from the same application, on a public path. Those pages need the tag as much as the pricing page does, so put them in the public group rather than leaving them to inherit whichever layout they happened to land under.

If the docs are a separate site on a subdomain instead, that is another origin for the allowlist and another crawl target, and it is usually where the best answerable material on the whole product lives.

Where the answerable material lives

Source material on a Next.js SaaS company site
The pricing grid as rendered, and the rules that stay in the repositoryA crawl reads the rendered page. It cannot read the configuration module the page was generated from, so any tier rule that exists only in code, what counts as a seat, whether a deactivated member still bills, what happens when a limit is reached, exists nowhere the assistant can reach. On this stack that gap is the norm rather than the exception.
The public documentation routeThe highest value material on the site and the least curated. Index all of it rather than choosing the pages you think matter, because the ones you would never have picked are the ones people search for late at night.
In-product copy, which is behind the auth boundary and unreachableEmpty states, tooltips, the onboarding checklist, the error messages. This is frequently the best written explanatory material a subscription business owns and a crawl will never see a word of it. If you want it answerable, it has to be exported and uploaded.
The changelog or release notes routeAnswers when did this change and did you break this deliberately, which arrives constantly from long standing customers. Keep it public and keep the dates on the entries, because the date is what makes an old entry safe to quote.

The first thing to get right

Do this first
Move the tag out of the root layout and into the public route group, then load a dashboard URL and confirm the corner is empty.

Everything else on this pairing can be corrected after launch by re-indexing. This one cannot, because what it produces is customers forming an expectation about what the assistant can do while standing inside the product, and that expectation is set on the first screen they see it on.

The failure that belongs to this combination

The launcher in the corner of the product changes what gets asked

On the marketing site the questions are about plans, features and whether it will work for them, all of which are documented and answerable. Inside the dashboard the questions are why was I charged this, is my invoice issued, how many seats am I using. It holds no view of any of that and correctly refuses.

So the refusal rate climbs, the conversation log fills with account questions, and the reasonable conclusion from the numbers is that the assistant does not work. The numbers are real. They are measuring an audience the widget was never scoped for.

There is a second cost that shows up in a bug report rather than in a metric: a fixed launcher in the bottom corner of an application sits on top of whatever your own interface put there, which on a dense product screen is usually something clickable.

Before you go live

  • The origin the page is served from has to be on the allowlist for that assistant, or nothing renders and the browser console says which origin was refused. An apex domain and its www are two different origins to a browser, so list both, along with any staging or preview host you want it to work on.
  • Open the site as a visitor would, on the pages a SaaS company visitor actually lands on, and ask it something only your own material could answer. A widget that renders is not the same as a widget that has read anything.

Questions

Our app is on its own subdomain already. Is there anything to do?
The boundary is enforced for you, so the only decision left is whether you want the assistant on that subdomain deliberately. Most subscription businesses do not, because in-product questions are account questions. If you do, it is a separate install with its own allowlist entry and it should have material written for signed in customers rather than for prospects.
Can it answer questions about a customer's usage or their next invoice?
No. It reads indexed pages and documents and has no view of billing state, seats or usage. What it can do is explain how a charge is calculated from your published policy, which is often the real question, then take a name and an email so somebody can look up the figure itself.
Where should the tier boundary rules live so it can answer them?
On a public page, ideally the pricing page or one linked from it. Writing them down once fixes this for the assistant and for every buyer who could not work them out either, and it moves the rules out of a configuration module that no crawl and no customer will ever read.

Keep reading

Try it on your own material

Upload a document or point it at your site, paste one line of HTML, then ask it something only your business could answer.