Cosmic Insights for Astro
Cosmic Insights ships as a single <script> tag that works in every framework. No npm package, no Astro integration to install. The tracker hooks history.pushState / popstate natively, so View Transitions and SPA navigations are captured automatically.
If your app is built with Cosmic AI Build, the tag is injected for you. The instructions below cover manual installs.
Project id
Find your project id in the dashboard under Project, Settings, Basic settings (the PROJECT ID field has a copy button). It is not a secret.
# .env
PUBLIC_COSMIC_INSIGHTS_PROJECT=your_project_id
Install
Add the script to your base layout's <head>:
---
// src/layouts/Base.astro
const projectId = import.meta.env.PUBLIC_COSMIC_INSIGHTS_PROJECT;
---
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{Astro.props.title}</title>
<script
is:inline
defer
src="https://insights.cosmicinsights.dev/script.js"
data-project={projectId}
/>
</head>
<body>
<slot />
</body>
</html>
is:inline keeps Astro from processing the tag so the defer attribute and the data-project value reach the browser unchanged.
Object attribution
Render a single <meta name="cosmic-context"> tag in the page head with JSON content identifying the Cosmic object. The tracker re-reads it on every SPA navigation.
---
// src/pages/blog/[slug].astro
import Base from '../../layouts/Base.astro';
import { getPost } from '../../lib/cosmic';
const post = await getPost(Astro.params.slug);
const context = JSON.stringify({
object_id: post.id,
object_type: post.type_slug,
});
---
<Base title={post.title}>
<meta name="cosmic-context" content={context} slot="head" />
<article>{/* ... */}</article>
</Base>
If your layout doesn't expose a head slot, render the <meta> tag inside the layout itself and pass context as a prop.
Custom events
window.cosmicInsights('signup', { plan: 'team' });
window.cosmicInsights('order_paid', { revenue_cents: 4900, currency: 'USD' });
Recognized top-level fields like revenue_cents and object_id are promoted onto the event row; everything else is stored in event_props.
See Attribution for the full precedence model.