На Astro устанавливать проще всего, и здесь есть одна неочевидная деталь: тег идёт в <head>, а не перед закрывающим </body>, как говорит общая инструкция. Это не вкус. Именно это позволяет тегу пережить переход на стороне клиента, и причина — внизу страницы.

Сначала возьмите сниппет в своей панели. Выглядит он так, с вашим собственным идентификатором сайта в пути:

<script src="https://t.skomi.com/s/your-site-id.js" defer></script>

Поставьте его в общий макет

В тот макет, которым пользуется каждая страница (обычно src/layouts/Layout.astro), внутрь <head>:

---
// src/layouts/Layout.astro
---
<html lang="ru">
  <head>
    <meta charset="utf-8" />
    <slot name="head" />
    <script is:inline defer src="https://t.skomi.com/s/your-site-id.js"></script>
  </head>
  <body>
    <slot />
  </body>
</html>

is:inline важен. Astro обрабатывает теги <script> (собирает их, превращает в модули, компилирует TypeScript) для любого тега, у которого единственный атрибут это src. is:inline велит отрисовать тег в HTML ровно так, как написано, а это и нужно для скрипта, отдаваемого с чужого домена. (Любой другой атрибут неявно тоже добавляет is:inline, так что defer выше сделал бы это сам; написанное явно говорит, что вы имели в виду.)

Если вы используете <ClientRouter />

По умолчанию Astro — многостраничное приложение: каждый переход это настоящая загрузка страницы, и думать больше не о чем.

Добавьте <ClientRouter /> (переходы между страницами), и оно становится маршрутизатором на стороне клиента. Skomi справляется с этим без всякой помощи: маршрутизатор переходит через history.pushStatereplaceState, где ссылка об этом просит), а скрипт Skomi оборачивает оба и слушает popstate, так что каждый переход становится просмотром страницы. Покидаемая страница закрывается первой, поэтому время на ней принадлежит ей, а не следующей.

Не добавляйте к этому тегу data-astro-rerun. Этот атрибут существует, чтобы заставить встроенный скрипт выполниться снова после каждого перехода, а здесь это значит запускать трекер второй, третий и четвёртый раз, и считать каждый визит столько же раз. Не ставьте его.

Почему head, а не перед </body>

Документация Astro точна в том, что переход делает с документом, и с двумя половинами он обходится противоположно:

  • <body> заменяется целиком телом новой страницы.
  • В <head> «скрипты остаются на месте, если они есть и на новой странице».

Поэтому тег в конце body удаляется и вставляется заново при каждом переходе (что запускает его снова), а тот же тег в head макета, общего для всех страниц, опознаётся как уже присутствующий и остаётся нетронутым. Он выполняется один раз, при первой загрузке, и дальше работает.

На сайте без <ClientRouter /> оба положения ведут себя одинаково, так что head — правильный ответ в любом случае, и менять ничего не придётся, если вы добавите переходы позже.

Проверьте, что работает

Загрузите страницу на настоящем домене, перейдите на вторую, потом обратно на первую. Вы должны увидеть три просмотра страниц, по одному на переход, а не шесть. Шесть означают, что тег выполняется заново, то есть он в body или несёт data-astro-rerun.

Если не приходит вообще ничего, смотрите что проверить, когда сниппет не работает.

Две вещи, которые выглядят поломкой и ею не являются

С localhost ничего не собирается. Ваш адрес разработки — не тот домен, который вы зарегистрировали, поэтому обращения с него отклоняет проверка источника. Выложите на настоящий домен или его поддомен и смотрите там.

Политика безопасности содержимого будет его блокировать, пока ей не скажут не делать этого. Скрипт и данные, которые он шлёт, используют один хост:

script-src  https://t.skomi.com
connect-src https://t.skomi.com