---
title: "SSR apps"
description: "Server-rendered apps (Rails, Django, Express, Next.js Pages Router, Remix) work like static sites. The CanaryLytics snippet runs in the browser after the page loads."
last_updated: "2026-07-30"
---

# SSR apps

Server-rendered pages work exactly like static sites from the tracker's point of view: the snippet is inert until the browser parses and executes it, so it doesn't matter whether the surrounding HTML came from a template on disk or was rendered per-request on the server.

Include the snippet in whatever shared layout or partial renders your `<head>` (or the end of `<body>`):

```html
<script src="https://cdn.analytics.canarycoders.es/lytics.js" data-domain="myapp.com" defer></script>
```

That is the whole integration for classic server-rendered apps. There is no client-side router to patch and no hydration timing to worry about.

If your SSR framework layers a client-side router on top of the initial server render (Next.js, Remix, SvelteKit, Nuxt, and similar "SSR + SPA navigation" frameworks), the snippet's `history.pushState`/`replaceState` patching picks up client-side route changes automatically once the app hydrates.

## Related

<CardGrid>
  <LinkCard title="SPAs & client-side routing" description="How post-hydration navigations are tracked." href="/docs/environments/spas/" />
  <LinkCard title="Framework integrations" description="Exactly where the tag goes in specific frameworks." href="/docs/environments/framework-integrations/" />
</CardGrid>

## Sitemap

- [Docs sitemap](https://analytics.canarycoders.es/docs/sitemap.md)
- [Full documentation as a single file](https://analytics.canarycoders.es/llms-full.txt)
