Plausible - Privacy-First Analytics
Czym jest Plausible?
Plausible Analytics to lekka, open source'owa platforma analityczna stworzona jako alternatywa dla Google Analytics z myślą o prywatności użytkowników. Założona w 2019 roku w Estonii przez Uku Täht i Marko Saric, Plausible wyrosło z potrzeby posiadania narzędzia analitycznego, które nie wymaga cookies, bannerów zgody GDPR i nie zbiera danych osobowych.
W przeciwieństwie do tradycyjnych narzędzi analitycznych, które śledzą użytkowników przez całą sieć za pomocą cookies third-party, Plausible używa unikalnego podejścia opartego na hashowaniu adresów IP w połączeniu z User Agent. To oznacza, że każda wizyta jest anonimowa, a Plausible nie buduje profili użytkowników ani nie sprzedaje danych reklamodawcom.
Historia i filozofia Plausible
Plausible powstało jako odpowiedź na rosnące obawy dotyczące prywatności w internecie i coraz bardziej skomplikowane regulacje jak GDPR (Europa), CCPA (Kalifornia) czy LGPD (Brazylia). Twórcy zauważyli, że większość właścicieli stron potrzebuje tylko podstawowych metryk - ilu ludzi odwiedza stronę, skąd przychodzą i które strony są popularne.
Google Analytics oferuje tysiące metryk i wymiarów, ale większość z nich nie jest potrzebna zwykłym twórcom treści czy małym firmom. Za to wymaga akceptacji skomplikowanej polityki prywatności, instalacji bannerów cookie i potencjalnie naraża na kary za naruszenie GDPR sięgające 4% rocznego obrotu.
Plausible to filozofia "less is more" - prosty dashboard z najważniejszymi informacjami, bez zbędnego szumu i bez kompromisów w kwestii prywatności.
Dlaczego Plausible?
1. Brak cookies = Brak GDPR bannerów
Plausible nie używa cookies ani żadnej formy persistent storage. Nie musisz wyświetlać irytujących banerów z pytaniem o zgodę na cookies. Twoja strona ładuje się szybciej i wygląda profesjonalniej bez tych pop-upów.
2. Ekstremalnie lekki skrypt
Skrypt Plausible waży mniej niż 1KB (gzipped), podczas gdy Google Analytics to ponad 45KB. To oznacza:
- Szybsze ładowanie strony
- Lepszy Core Web Vitals score
- Niższe zużycie transferu dla odwiedzających
- Mniejszy ślad węglowy strony
3. Pełna zgodność z przepisami
Plausible jest w pełni zgodny z:
- GDPR (Europa)
- CCPA (Kalifornia)
- PECR (UK)
- LGPD (Brazylia)
- PIPEDA (Kanada)
Dane są przechowywane na serwerach w Unii Europejskiej, co jest wymogiem wielu europejskich firm i instytucji.
4. Open Source i Self-hosting
Plausible jest w pełni open source (licencja AGPL). Możesz:
- Zobaczyć dokładnie, jak działa kod
- Uruchomić własną instancję na swoich serwerach
- Mieć 100% kontrolę nad danymi
- Nigdy nie martwić się o vendor lock-in
5. Prosty, czytelny dashboard
Zamiast setek raportów i wymiarów, dostajesz jeden elegancki dashboard z najważniejszymi informacjami:
- Liczba odwiedzających (unique visitors)
- Odsłony (pageviews)
- Współczynnik odrzuceń (bounce rate)
- Czas na stronie
- Źródła ruchu
- Popularne strony
- Lokalizacje geograficzne
- Urządzenia i przeglądarki
6. Etyczne podejście do biznesu
Plausible to bootstrapped firma bez zewnętrznych inwestorów. To oznacza:
- Brak presji na monetyzację danych użytkowników
- Transparentny model biznesowy (płacisz za usługę, nie jesteś produktem)
- Długoterminowa stabilność bez ryzyka przejęcia przez korporację
Plausible vs Google Analytics
| Cecha | Plausible | Google Analytics 4 |
|---|---|---|
| Cookies | Nie | Tak (first-party) |
| GDPR banner | Nie wymaga | Wymaga |
| Rozmiar skryptu | <1KB | 45KB+ |
| Dane osobowe | Nie zbiera | Zbiera |
| Profiling użytkowników | Nie | Tak |
| Udostępnianie Google | Nie | Tak (domyślnie) |
| Open source | Tak (AGPL) | Nie |
| Self-hosting | Tak | Nie |
| Cena | Od $9/mo | "Darmowy"* |
| Kompleksowość | Prosty | Bardzo złożony |
| Retencja danych | Nieokreślona | 2-14 miesięcy |
| Real-time | Tak | Ograniczony |
| Lokalizacja danych | EU (Niemcy) | USA (Google Cloud) |
*Google Analytics jest "darmowy", ale płacisz danymi swoich użytkowników, które Google wykorzystuje do reklam.
Plausible vs inne alternatywy
| Cecha | Plausible | Fathom | Simple Analytics | Matomo |
|---|---|---|---|---|
| Open source | Tak | Nie | Nie | Tak |
| Self-host | Tak | Nie | Nie | Tak |
| Cena (start) | $9/mo | $14/mo | $9/mo | Free |
| Cookies | Nie | Nie | Nie | Opcjonalne |
| Rozmiar JS | <1KB | 2KB | 3KB | 22KB+ |
| EU hosting | Tak | Tak | Tak | Opcjonalne |
| Real-time | Tak | Tak | Tak | Tak |
| Custom events | Tak | Tak | Tak | Tak |
| Funnels | Tak | Tak | Tak | Tak |
| API | Tak | Tak | Tak | Tak |
Instalacja Plausible
Podstawowa instalacja (HTML)
Dodaj skrypt do sekcji <head> swojej strony:
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Moja strona</title>
<!-- Plausible Analytics -->
<script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.js">
</script>
</head>
<body>
<!-- Zawartość strony -->
</body>
</html>Next.js App Router
// app/layout.tsx
import Script from 'next/script'
export default function RootLayout({
children
}: {
children: React.ReactNode
}) {
return (
<html lang="pl">
<head>
<Script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.js"
strategy="afterInteractive"
/>
</head>
<body>{children}</body>
</html>
)
}Next.js Pages Router
// pages/_app.tsx
import Script from 'next/script'
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.js"
strategy="afterInteractive"
/>
<Component {...pageProps} />
</>
)
}Remix
// app/root.tsx
import { Links, Meta, Outlet, Scripts } from '@remix-run/react'
export default function App() {
return (
<html lang="pl">
<head>
<Meta />
<Links />
<script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.js"
/>
</head>
<body>
<Outlet />
<Scripts />
</body>
</html>
)
}Astro
---
// src/layouts/Layout.astro
---
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>{title}</title>
<script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.js">
</script>
</head>
<body>
<slot />
</body>
</html>Gatsby
// gatsby-ssr.js
import React from 'react'
export const onRenderBody = ({ setHeadComponents }) => {
setHeadComponents([
<script
key="plausible"
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.js"
/>
])
}Nuxt.js 3
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
script: [
{
defer: true,
'data-domain': 'twojadomena.pl',
src: 'https://plausible.io/js/script.js'
}
]
}
}
})SvelteKit
<!-- src/app.html -->
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
<script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.js">
</script>
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>Custom Events
Śledzenie zdarzeń z JavaScript
// Deklaracja typów dla TypeScript
declare global {
interface Window {
plausible: (
event: string,
options?: {
props?: Record<string, string | number | boolean>
callback?: () => void
revenue?: { currency: string; amount: number }
}
) => void
}
}
// Podstawowe zdarzenie
function trackSignup() {
window.plausible('Signup')
}
// Zdarzenie z właściwościami
function trackPurchase(plan: string, price: number) {
window.plausible('Purchase', {
props: {
plan,
price: price.toString()
}
})
}
// Zdarzenie z revenue tracking
function trackSale(amount: number, currency: string = 'PLN') {
window.plausible('Sale', {
revenue: { currency, amount }
})
}
// Zdarzenie z callback
function trackDownload(fileName: string) {
window.plausible('Download', {
props: { file: fileName },
callback: () => {
console.log('Event tracked successfully')
}
})
}Hook do React
// hooks/usePlausible.ts
import { useCallback } from 'react'
type PlausibleEvent = {
name: string
props?: Record<string, string | number | boolean>
revenue?: { currency: string; amount: number }
}
export function usePlausible() {
const trackEvent = useCallback(({ name, props, revenue }: PlausibleEvent) => {
if (typeof window !== 'undefined' && window.plausible) {
window.plausible(name, { props, revenue })
}
}, [])
const trackPageview = useCallback((url?: string) => {
if (typeof window !== 'undefined' && window.plausible) {
window.plausible('pageview', {
props: url ? { url } : undefined
})
}
}, [])
return { trackEvent, trackPageview }
}
// Użycie w komponencie
function PricingCard({ plan, price }: { plan: string; price: number }) {
const { trackEvent } = usePlausible()
const handlePurchase = () => {
trackEvent({
name: 'Purchase',
props: { plan },
revenue: { currency: 'PLN', amount: price }
})
}
return (
<button onClick={handlePurchase}>
Kup plan {plan} za {price} PLN
</button>
)
}Automatyczne śledzenie kliknięć
<!-- Dodaj klasę plausible-event-name=NAZWA do elementu -->
<a
href="/pricing"
class="plausible-event-name=CTA+Click"
>
Zobacz cennik
</a>
<!-- Z właściwościami -->
<button
class="plausible-event-name=Button+Click plausible-event-variant=primary"
>
Zapisz się
</button>
<!-- Dla formularzy -->
<form
action="/submit"
class="plausible-event-name=Form+Submit"
>
<input type="email" name="email" required />
<button type="submit">Wyślij</button>
</form>Rozszerzone opcje skryptu
<!-- Automatyczne śledzenie outbound links -->
<script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.outbound-links.js">
</script>
<!-- Śledzenie pobrań plików -->
<script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.file-downloads.js">
</script>
<!-- Wszystkie rozszerzenia -->
<script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.tagged-events.outbound-links.file-downloads.js">
</script>
<!-- Hash-based routing (SPA) -->
<script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.hash.js">
</script>
<!-- Manual pageview tracking dla SPA -->
<script
defer
data-domain="twojadomena.pl"
src="https://plausible.io/js/script.manual.js">
</script>Goals & Conversions
Definiowanie celów w dashboardzie
W panelu Plausible możesz zdefiniować różne typy celów:
1. Odwiedziny strony (Pageview goals)
/pricing- odwiedziny strony cennika/thank-you- strona podziękowania po zakupie/signup/complete- zakończenie rejestracji
2. Custom events
Signup- rejestracja użytkownikaPurchase- zakupDownload- pobranie plikuNewsletter- zapis do newslettera
3. Funnels (lejki konwersji)
Funnel: Proces zakupowy
1. /products →
2. /cart →
3. /checkout →
4. /thank-you
Konwersja: 2.3%Revenue tracking
// Śledzenie przychodu
function trackPurchase(orderId: string, amount: number) {
window.plausible('Purchase', {
revenue: {
currency: 'PLN',
amount
},
props: {
order_id: orderId
}
})
}
// Przykład: e-commerce checkout
async function completeCheckout(cart: CartItem[]) {
const total = cart.reduce((sum, item) => sum + item.price * item.quantity, 0)
const response = await fetch('/api/checkout', {
method: 'POST',
body: JSON.stringify(cart)
})
if (response.ok) {
const { orderId } = await response.json()
// Track w Plausible
window.plausible('Purchase', {
revenue: { currency: 'PLN', amount: total },
props: {
order_id: orderId,
items_count: cart.length.toString()
}
})
}
}Filtrowanie i segmentacja
Dostępne filtry w dashboardzie
Plausible pozwala filtrować dane według:
Źródła ruchu:
- Source (Google, Facebook, Twitter, itp.)
- Referrer (konkretna strona odsyłająca)
- UTM parameters (campaign, source, medium, term, content)
Technologia:
- Browser (Chrome, Firefox, Safari, Edge)
- OS (Windows, macOS, iOS, Android, Linux)
- Device type (Desktop, Mobile, Tablet)
- Country / Region / City
Strony:
- Entry page (strona wejścia)
- Exit page (strona wyjścia)
- Page (odwiedzona strona)
UTM tracking
<!-- Link z UTM parameters -->
<a href="https://twojadomena.pl?utm_source=newsletter&utm_medium=email&utm_campaign=summer_sale">
Sprawdź promocję
</a>// Generowanie linków z UTM w JavaScript
function createUtmLink(
baseUrl: string,
params: {
source: string
medium: string
campaign: string
term?: string
content?: string
}
) {
const url = new URL(baseUrl)
url.searchParams.set('utm_source', params.source)
url.searchParams.set('utm_medium', params.medium)
url.searchParams.set('utm_campaign', params.campaign)
if (params.term) url.searchParams.set('utm_term', params.term)
if (params.content) url.searchParams.set('utm_content', params.content)
return url.toString()
}
// Użycie
const newsletterLink = createUtmLink('https://mojsklep.pl/promocja', {
source: 'newsletter',
medium: 'email',
campaign: 'black_friday_2024'
})Plausible API
Stats API
// Pobieranie statystyk z Plausible API
const PLAUSIBLE_API_KEY = process.env.PLAUSIBLE_API_KEY
const SITE_ID = 'twojadomena.pl'
interface PlausibleStats {
results: {
visitors: { value: number }
pageviews: { value: number }
bounce_rate: { value: number }
visit_duration: { value: number }
}
}
async function getStats(period: string = '30d'): Promise<PlausibleStats> {
const response = await fetch(
`https://plausible.io/api/v1/stats/aggregate?` +
`site_id=${SITE_ID}&period=${period}&` +
`metrics=visitors,pageviews,bounce_rate,visit_duration`,
{
headers: {
Authorization: `Bearer ${PLAUSIBLE_API_KEY}`
}
}
)
return response.json()
}
// Pobieranie top stron
interface TopPages {
results: Array<{
page: string
visitors: number
}>
}
async function getTopPages(limit: number = 10): Promise<TopPages> {
const response = await fetch(
`https://plausible.io/api/v1/stats/breakdown?` +
`site_id=${SITE_ID}&period=30d&property=event:page&limit=${limit}`,
{
headers: {
Authorization: `Bearer ${PLAUSIBLE_API_KEY}`
}
}
)
return response.json()
}Real-time API
// Pobieranie aktywnych użytkowników
async function getCurrentVisitors(): Promise<number> {
const response = await fetch(
`https://plausible.io/api/v1/stats/realtime/visitors?site_id=${SITE_ID}`,
{
headers: {
Authorization: `Bearer ${PLAUSIBLE_API_KEY}`
}
}
)
return response.json()
}
// Komponent pokazujący aktywnych użytkowników
function LiveVisitors() {
const [visitors, setVisitors] = useState<number>(0)
useEffect(() => {
const fetchVisitors = async () => {
const count = await getCurrentVisitors()
setVisitors(count)
}
fetchVisitors()
const interval = setInterval(fetchVisitors, 30000) // co 30 sekund
return () => clearInterval(interval)
}, [])
return (
<div className="flex items-center gap-2">
<span className="relative flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" />
<span className="relative inline-flex rounded-full h-3 w-3 bg-green-500" />
</span>
<span>{visitors} aktywnych użytkowników</span>
</div>
)
}Events API
// Wysyłanie zdarzeń bezpośrednio przez API (server-side)
async function trackServerEvent(
eventName: string,
props?: Record<string, string>,
userAgent?: string,
ip?: string
) {
await fetch('https://plausible.io/api/event', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': userAgent || 'Node.js',
'X-Forwarded-For': ip || ''
},
body: JSON.stringify({
name: eventName,
url: `https://${SITE_ID}`,
domain: SITE_ID,
props
})
})
}
// Użycie w API route (Next.js)
export async function POST(request: Request) {
const { action, data } = await request.json()
// Logika biznesowa...
// Track w Plausible
await trackServerEvent(
'API Action',
{ action, status: 'success' },
request.headers.get('user-agent') || undefined,
request.headers.get('x-forwarded-for') || undefined
)
return Response.json({ success: true })
}Self-hosting Plausible
Docker Compose setup
# docker-compose.yml
version: "3.8"
services:
plausible:
image: plausible/analytics:v2.0
restart: always
command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
depends_on:
- plausible_db
- plausible_events_db
ports:
- 8000:8000
env_file:
- plausible-conf.env
plausible_db:
image: postgres:14-alpine
restart: always
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=postgres
plausible_events_db:
image: clickhouse/clickhouse-server:23.3.7.5-alpine
restart: always
volumes:
- event-data:/var/lib/clickhouse
- ./clickhouse/clickhouse-config.xml:/etc/clickhouse-server/config.d/logging.xml:ro
- ./clickhouse/clickhouse-user-config.xml:/etc/clickhouse-server/users.d/logging.xml:ro
ulimits:
nofile:
soft: 262144
hard: 262144
volumes:
db-data:
event-data:Konfiguracja environment
# plausible-conf.env
# Required settings
BASE_URL=https://analytics.twojadomena.pl
SECRET_KEY_BASE=losowy-64-znakowy-string-wygeneruj-przez-openssl
# Database
DATABASE_URL=postgres://postgres:postgres@plausible_db:5432/plausible_db
CLICKHOUSE_DATABASE_URL=http://plausible_events_db:8123/plausible_events_db
# Email (opcjonalnie, dla powiadomień)
MAILER_EMAIL=plausible@twojadomena.pl
SMTP_HOST_ADDR=smtp.twojadomena.pl
SMTP_HOST_PORT=587
SMTP_USER_NAME=plausible@twojadomena.pl
SMTP_USER_PWD=haslo-smtp
SMTP_HOST_SSL_ENABLED=false
SMTP_RETRIES=2
# Opcjonalne
DISABLE_REGISTRATION=true
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=Uruchomienie
# Pobierz pliki konfiguracyjne
git clone https://github.com/plausible/community-edition.git plausible
cd plausible
# Wygeneruj secret key
openssl rand -base64 64 | tr -d '\n'
# Edytuj plausible-conf.env z wygenerowanym kluczem
# Uruchom
docker compose up -d
# Sprawdź logi
docker compose logs -f plausible
# Plausible będzie dostępny na http://localhost:8000Nginx reverse proxy
# /etc/nginx/sites-available/plausible
server {
listen 80;
server_name analytics.twojadomena.pl;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name analytics.twojadomena.pl;
ssl_certificate /etc/letsencrypt/live/analytics.twojadomena.pl/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analytics.twojadomena.pl/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Cache dla skryptu JS
location = /js/script.js {
proxy_pass http://127.0.0.1:8000/js/script.js;
proxy_set_header Host $host;
proxy_cache_valid 200 1h;
add_header Cache-Control "public, max-age=3600";
}
}Proxy skryptu przez własny serwer
Aby uniknąć blokowania przez ad-blockery:
// app/api/script.js/route.ts (Next.js)
export async function GET() {
const response = await fetch('https://plausible.io/js/script.js')
const script = await response.text()
// Zamień endpoint na własny
const modifiedScript = script.replace(
'https://plausible.io/api/event',
'https://twojadomena.pl/api/event'
)
return new Response(modifiedScript, {
headers: {
'Content-Type': 'application/javascript',
'Cache-Control': 'public, max-age=3600'
}
})
}
// app/api/event/route.ts
export async function POST(request: Request) {
const body = await request.text()
await fetch('https://plausible.io/api/event', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': request.headers.get('user-agent') || '',
'X-Forwarded-For': request.headers.get('x-forwarded-for') || ''
},
body
})
return new Response('ok')
}Integracja z frameworkami
next-plausible
npm install next-plausible// app/layout.tsx
import PlausibleProvider from 'next-plausible'
export default function RootLayout({
children
}: {
children: React.ReactNode
}) {
return (
<html lang="pl">
<head>
<PlausibleProvider
domain="twojadomena.pl"
trackOutboundLinks
trackFileDownloads
taggedEvents
/>
</head>
<body>{children}</body>
</html>
)
}
// Użycie hooka
'use client'
import { usePlausible } from 'next-plausible'
function MyComponent() {
const plausible = usePlausible()
const handleClick = () => {
plausible('Button Click', {
props: { location: 'header', variant: 'primary' }
})
}
return <button onClick={handleClick}>Kliknij</button>
}@plausible/tracker
npm install @plausible/tracker// lib/plausible.ts
import Plausible from '@plausible/tracker'
export const plausible = Plausible({
domain: 'twojadomena.pl',
trackLocalhost: true, // dla developmentu
apiHost: 'https://plausible.io' // lub self-hosted URL
})
// Użycie
import { plausible } from '@/lib/plausible'
plausible.trackEvent('Signup', {
props: { plan: 'pro' }
})
// Z auto-tracking
plausible.enableAutoPageviews()
plausible.enableAutoOutboundTracking()Vue.js plugin
// plugins/plausible.ts
import { createPlausible } from 'vue-plausible'
export default defineNuxtPlugin((nuxtApp) => {
const plausible = createPlausible({
domain: 'twojadomena.pl',
trackLocalhost: false
})
nuxtApp.vueApp.use(plausible)
})
// Użycie w komponencie
<script setup>
import { usePlausible } from 'vue-plausible'
const { trackEvent } = usePlausible()
function handleClick() {
trackEvent('Button Click')
}
</script>Cennik Plausible
Plausible Cloud
| Pageviews / miesiąc | Cena miesięcznie | Cena rocznie (zniżka) |
|---|---|---|
| 10,000 | $9 | $90 (17% off) |
| 100,000 | $19 | $190 (17% off) |
| 200,000 | $29 | $290 (17% off) |
| 500,000 | $49 | $490 (17% off) |
| 1,000,000 | $69 | $690 (17% off) |
| 2,000,000 | $89 | $890 (17% off) |
| 5,000,000 | $129 | $1,290 (17% off) |
| 10,000,000+ | Custom | Custom |
Co zawiera każdy plan:
- Nieograniczona liczba stron
- Nieograniczona liczba użytkowników zespołu
- Wszystkie funkcje (goals, funnels, custom events)
- Email reports
- API access
- Data export
- EU data hosting
Self-hosted
| Opcja | Koszt |
|---|---|
| Community Edition | Darmowy (AGPL) |
| Enterprise features | Licencja komercyjna |
Wymagania self-hosted:
- 2GB RAM minimum
- 20GB dysku (zależy od ruchu)
- Docker i Docker Compose
- Domena z SSL (Let's Encrypt)
FAQ - Najczęściej zadawane pytania
Czy Plausible naprawdę nie używa cookies?
Tak, Plausible nie używa żadnych cookies ani localStorage. Identyfikacja unikalnych wizyt opiera się na hashowaniu: IP + User Agent + domena + data. Hash jest tworzony na nowo każdego dnia, więc nie ma możliwości śledzenia użytkownika między dniami.
Czy muszę wyświetlać banner GDPR?
Nie, jeśli używasz tylko Plausible. Ponieważ Plausible nie zbiera danych osobowych i nie używa cookies, nie wymaga zgody użytkownika zgodnie z GDPR. Jednak jeśli używasz innych narzędzi wymagających zgody, banner i tak będzie potrzebny.
Jak Plausible radzi sobie z ad-blockerami?
Domyślny skrypt Plausible jest blokowany przez niektóre ad-blockery. Rozwiązania:
- Proxy skryptu przez własny serwer
- Użycie własnej subdomeny (analytics.twojadomena.pl)
- Self-hosting całej instancji
Czy mogę używać Plausible na wielu domenach?
Tak, każda domena to osobna "strona" w dashboardzie. Możesz też agregować dane z wielu subdomen na jednym dashboardzie.
Jak długo Plausible przechowuje dane?
Plausible Cloud przechowuje dane bezterminowo - nie ma limitu retencji. W wersji self-hosted możesz skonfigurować własne zasady retencji.
Czy Plausible śledzi subdomeny?
Możesz skonfigurować Plausible do śledzenia:
- Tylko głównej domeny
- Wszystkich subdomen razem
- Każdej subdomeny osobno
<!-- Wszystkie subdomeny razem -->
<script data-domain="twojadomena.pl" src="..."></script>
<!-- Konkretna subdomena -->
<script data-domain="blog.twojadomena.pl" src="..."></script>Jak zmigrować z Google Analytics?
- Dodaj skrypt Plausible obok GA
- Porównuj dane przez 2-4 tygodnie
- Zdefiniuj cele odpowiadające eventom z GA
- Usuń skrypt GA po weryfikacji
Plausible oferuje też import danych historycznych z Google Analytics.
Czy mogę używać Plausible do śledzenia aplikacji mobilnych?
Plausible jest przeznaczony głównie do stron web. Dla aplikacji mobilnych rozważ dedykowane rozwiązania jak Mixpanel, Amplitude lub PostHog. Jednak możesz używać Plausible API do wysyłania zdarzeń z aplikacji.
Plausible - privacy-first analytics
What is Plausible?
Plausible Analytics is a lightweight, open-source analytics platform created as an alternative to Google Analytics with user privacy in mind. Founded in 2019 in Estonia by Uku Taht and Marko Saric, Plausible grew out of the need for an analytics tool that does not require cookies, GDPR consent banners, and does not collect personal data.
Unlike traditional analytics tools that track users across the web using third-party cookies, Plausible uses a unique approach based on hashing IP addresses combined with User Agent. This means every visit is anonymous, and Plausible does not build user profiles or sell data to advertisers.
History and philosophy of Plausible
Plausible was created as a response to growing concerns about internet privacy and increasingly complex regulations like GDPR (Europe), CCPA (California), and LGPD (Brazil). The creators noticed that most website owners only need basic metrics -- how many people visit the site, where they come from, and which pages are popular.
Google Analytics offers thousands of metrics and dimensions, but most of them are not needed by regular content creators or small businesses. Yet it requires accepting a complicated privacy policy, installing cookie banners, and potentially exposes you to GDPR fines of up to 4% of annual revenue.
Plausible follows the "less is more" philosophy -- a simple dashboard with the most important information, without unnecessary noise and without compromising on privacy.
Why Plausible?
1. No cookies = no GDPR banners
Plausible does not use cookies or any form of persistent storage. You do not need to display annoying banners asking for cookie consent. Your site loads faster and looks more professional without those pop-ups.
2. Extremely lightweight script
The Plausible script weighs less than 1KB (gzipped), while Google Analytics is over 45KB. This means:
- Faster page loading
- Better Core Web Vitals score
- Lower bandwidth usage for visitors
- Smaller carbon footprint for your site
3. Full regulatory compliance
Plausible is fully compliant with:
- GDPR (Europe)
- CCPA (California)
- PECR (UK)
- LGPD (Brazil)
- PIPEDA (Canada)
Data is stored on servers in the European Union, which is a requirement for many European companies and institutions.
4. Open source and self-hosting
Plausible is fully open source (AGPL license). You can:
- See exactly how the code works
- Run your own instance on your servers
- Have 100% control over data
- Never worry about vendor lock-in
5. Simple, readable dashboard
Instead of hundreds of reports and dimensions, you get one elegant dashboard with the most important information:
- Unique visitors
- Pageviews
- Bounce rate
- Time on page
- Traffic sources
- Popular pages
- Geographic locations
- Devices and browsers
6. Ethical approach to business
Plausible is a bootstrapped company without external investors. This means:
- No pressure to monetize user data
- Transparent business model (you pay for the service, you are not the product)
- Long-term stability without the risk of corporate acquisition
Plausible vs Google Analytics
| Feature | Plausible | Google Analytics 4 |
|---|---|---|
| Cookies | No | Yes (first-party) |
| GDPR banner | Not required | Required |
| Script size | <1KB | 45KB+ |
| Personal data | Does not collect | Collects |
| User profiling | No | Yes |
| Sharing with Google | No | Yes (by default) |
| Open source | Yes (AGPL) | No |
| Self-hosting | Yes | No |
| Price | From $9/mo | "Free"* |
| Complexity | Simple | Very complex |
| Data retention | Indefinite | 2-14 months |
| Real-time | Yes | Limited |
| Data location | EU (Germany) | USA (Google Cloud) |
*Google Analytics is "free", but you pay with your users' data, which Google uses for advertising.
Plausible vs other alternatives
| Feature | Plausible | Fathom | Simple Analytics | Matomo |
|---|---|---|---|---|
| Open source | Yes | No | No | Yes |
| Self-host | Yes | No | No | Yes |
| Price (start) | $9/mo | $14/mo | $9/mo | Free |
| Cookies | No | No | No | Optional |
| JS size | <1KB | 2KB | 3KB | 22KB+ |
| EU hosting | Yes | Yes | Yes | Optional |
| Real-time | Yes | Yes | Yes | Yes |
| Custom events | Yes | Yes | Yes | Yes |
| Funnels | Yes | Yes | Yes | Yes |
| API | Yes | Yes | Yes | Yes |
Installing Plausible
Basic installation (HTML)
Add the script to the <head> section of your page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My website</title>
<!-- Plausible Analytics -->
<script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.js">
</script>
</head>
<body>
<!-- Page content -->
</body>
</html>Next.js App Router
// app/layout.tsx
import Script from 'next/script'
export default function RootLayout({
children
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<head>
<Script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.js"
strategy="afterInteractive"
/>
</head>
<body>{children}</body>
</html>
)
}Next.js Pages Router
// pages/_app.tsx
import Script from 'next/script'
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.js"
strategy="afterInteractive"
/>
<Component {...pageProps} />
</>
)
}Remix
// app/root.tsx
import { Links, Meta, Outlet, Scripts } from '@remix-run/react'
export default function App() {
return (
<html lang="en">
<head>
<Meta />
<Links />
<script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.js"
/>
</head>
<body>
<Outlet />
<Scripts />
</body>
</html>
)
}Astro
---
// src/layouts/Layout.astro
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>{title}</title>
<script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.js">
</script>
</head>
<body>
<slot />
</body>
</html>Gatsby
// gatsby-ssr.js
import React from 'react'
export const onRenderBody = ({ setHeadComponents }) => {
setHeadComponents([
<script
key="plausible"
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.js"
/>
])
}Nuxt.js 3
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
script: [
{
defer: true,
'data-domain': 'yourdomain.com',
src: 'https://plausible.io/js/script.js'
}
]
}
}
})SvelteKit
<!-- src/app.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
<script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.js">
</script>
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>Custom events
Tracking events with JavaScript
declare global {
interface Window {
plausible: (
event: string,
options?: {
props?: Record<string, string | number | boolean>
callback?: () => void
revenue?: { currency: string; amount: number }
}
) => void
}
}
function trackSignup() {
window.plausible('Signup')
}
function trackPurchase(plan: string, price: number) {
window.plausible('Purchase', {
props: {
plan,
price: price.toString()
}
})
}
function trackSale(amount: number, currency: string = 'USD') {
window.plausible('Sale', {
revenue: { currency, amount }
})
}
function trackDownload(fileName: string) {
window.plausible('Download', {
props: { file: fileName },
callback: () => {
console.log('Event tracked successfully')
}
})
}React hook
// hooks/usePlausible.ts
import { useCallback } from 'react'
type PlausibleEvent = {
name: string
props?: Record<string, string | number | boolean>
revenue?: { currency: string; amount: number }
}
export function usePlausible() {
const trackEvent = useCallback(({ name, props, revenue }: PlausibleEvent) => {
if (typeof window !== 'undefined' && window.plausible) {
window.plausible(name, { props, revenue })
}
}, [])
const trackPageview = useCallback((url?: string) => {
if (typeof window !== 'undefined' && window.plausible) {
window.plausible('pageview', {
props: url ? { url } : undefined
})
}
}, [])
return { trackEvent, trackPageview }
}
function PricingCard({ plan, price }: { plan: string; price: number }) {
const { trackEvent } = usePlausible()
const handlePurchase = () => {
trackEvent({
name: 'Purchase',
props: { plan },
revenue: { currency: 'USD', amount: price }
})
}
return (
<button onClick={handlePurchase}>
Buy {plan} plan for ${price}
</button>
)
}Automatic click tracking
<!-- Add the class plausible-event-name=NAME to the element -->
<a
href="/pricing"
class="plausible-event-name=CTA+Click"
>
View pricing
</a>
<!-- With properties -->
<button
class="plausible-event-name=Button+Click plausible-event-variant=primary"
>
Sign up
</button>
<!-- For forms -->
<form
action="/submit"
class="plausible-event-name=Form+Submit"
>
<input type="email" name="email" required />
<button type="submit">Submit</button>
</form>Extended script options
<!-- Automatic outbound link tracking -->
<script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.outbound-links.js">
</script>
<!-- File download tracking -->
<script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.file-downloads.js">
</script>
<!-- All extensions -->
<script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.tagged-events.outbound-links.file-downloads.js">
</script>
<!-- Hash-based routing (SPA) -->
<script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.hash.js">
</script>
<!-- Manual pageview tracking for SPA -->
<script
defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.manual.js">
</script>Goals & conversions
Defining goals in the dashboard
In the Plausible dashboard you can define different types of goals:
1. Pageview goals
/pricing- visits to the pricing page/thank-you- thank you page after purchase/signup/complete- registration completion
2. Custom events
Signup- user registrationPurchase- purchaseDownload- file downloadNewsletter- newsletter subscription
3. Funnels (conversion funnels)
Funnel: Purchase process
1. /products →
2. /cart →
3. /checkout →
4. /thank-you
Conversion: 2.3%Revenue tracking
function trackPurchase(orderId: string, amount: number) {
window.plausible('Purchase', {
revenue: {
currency: 'USD',
amount
},
props: {
order_id: orderId
}
})
}
async function completeCheckout(cart: CartItem[]) {
const total = cart.reduce((sum, item) => sum + item.price * item.quantity, 0)
const response = await fetch('/api/checkout', {
method: 'POST',
body: JSON.stringify(cart)
})
if (response.ok) {
const { orderId } = await response.json()
window.plausible('Purchase', {
revenue: { currency: 'USD', amount: total },
props: {
order_id: orderId,
items_count: cart.length.toString()
}
})
}
}Filtering and segmentation
Available filters in the dashboard
Plausible lets you filter data by:
Traffic sources:
- Source (Google, Facebook, Twitter, etc.)
- Referrer (specific referring page)
- UTM parameters (campaign, source, medium, term, content)
Technology:
- Browser (Chrome, Firefox, Safari, Edge)
- OS (Windows, macOS, iOS, Android, Linux)
- Device type (Desktop, Mobile, Tablet)
- Country / Region / City
Pages:
- Entry page
- Exit page
- Page (visited page)
UTM tracking
<!-- Link with UTM parameters -->
<a href="https://yourdomain.com?utm_source=newsletter&utm_medium=email&utm_campaign=summer_sale">
Check out the promotion
</a>function createUtmLink(
baseUrl: string,
params: {
source: string
medium: string
campaign: string
term?: string
content?: string
}
) {
const url = new URL(baseUrl)
url.searchParams.set('utm_source', params.source)
url.searchParams.set('utm_medium', params.medium)
url.searchParams.set('utm_campaign', params.campaign)
if (params.term) url.searchParams.set('utm_term', params.term)
if (params.content) url.searchParams.set('utm_content', params.content)
return url.toString()
}
const newsletterLink = createUtmLink('https://mystore.com/promo', {
source: 'newsletter',
medium: 'email',
campaign: 'black_friday_2024'
})Plausible API
Stats API
const PLAUSIBLE_API_KEY = process.env.PLAUSIBLE_API_KEY
const SITE_ID = 'yourdomain.com'
interface PlausibleStats {
results: {
visitors: { value: number }
pageviews: { value: number }
bounce_rate: { value: number }
visit_duration: { value: number }
}
}
async function getStats(period: string = '30d'): Promise<PlausibleStats> {
const response = await fetch(
`https://plausible.io/api/v1/stats/aggregate?` +
`site_id=${SITE_ID}&period=${period}&` +
`metrics=visitors,pageviews,bounce_rate,visit_duration`,
{
headers: {
Authorization: `Bearer ${PLAUSIBLE_API_KEY}`
}
}
)
return response.json()
}
interface TopPages {
results: Array<{
page: string
visitors: number
}>
}
async function getTopPages(limit: number = 10): Promise<TopPages> {
const response = await fetch(
`https://plausible.io/api/v1/stats/breakdown?` +
`site_id=${SITE_ID}&period=30d&property=event:page&limit=${limit}`,
{
headers: {
Authorization: `Bearer ${PLAUSIBLE_API_KEY}`
}
}
)
return response.json()
}Real-time API
async function getCurrentVisitors(): Promise<number> {
const response = await fetch(
`https://plausible.io/api/v1/stats/realtime/visitors?site_id=${SITE_ID}`,
{
headers: {
Authorization: `Bearer ${PLAUSIBLE_API_KEY}`
}
}
)
return response.json()
}
function LiveVisitors() {
const [visitors, setVisitors] = useState<number>(0)
useEffect(() => {
const fetchVisitors = async () => {
const count = await getCurrentVisitors()
setVisitors(count)
}
fetchVisitors()
const interval = setInterval(fetchVisitors, 30000)
return () => clearInterval(interval)
}, [])
return (
<div className="flex items-center gap-2">
<span className="relative flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" />
<span className="relative inline-flex rounded-full h-3 w-3 bg-green-500" />
</span>
<span>{visitors} active users</span>
</div>
)
}Events API
async function trackServerEvent(
eventName: string,
props?: Record<string, string>,
userAgent?: string,
ip?: string
) {
await fetch('https://plausible.io/api/event', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': userAgent || 'Node.js',
'X-Forwarded-For': ip || ''
},
body: JSON.stringify({
name: eventName,
url: `https://${SITE_ID}`,
domain: SITE_ID,
props
})
})
}
export async function POST(request: Request) {
const { action, data } = await request.json()
await trackServerEvent(
'API Action',
{ action, status: 'success' },
request.headers.get('user-agent') || undefined,
request.headers.get('x-forwarded-for') || undefined
)
return Response.json({ success: true })
}Self-hosting Plausible
Docker Compose setup
# docker-compose.yml
version: "3.8"
services:
plausible:
image: plausible/analytics:v2.0
restart: always
command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
depends_on:
- plausible_db
- plausible_events_db
ports:
- 8000:8000
env_file:
- plausible-conf.env
plausible_db:
image: postgres:14-alpine
restart: always
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=postgres
plausible_events_db:
image: clickhouse/clickhouse-server:23.3.7.5-alpine
restart: always
volumes:
- event-data:/var/lib/clickhouse
- ./clickhouse/clickhouse-config.xml:/etc/clickhouse-server/config.d/logging.xml:ro
- ./clickhouse/clickhouse-user-config.xml:/etc/clickhouse-server/users.d/logging.xml:ro
ulimits:
nofile:
soft: 262144
hard: 262144
volumes:
db-data:
event-data:Environment configuration
# plausible-conf.env
# Required settings
BASE_URL=https://analytics.yourdomain.com
SECRET_KEY_BASE=random-64-character-string-generate-with-openssl
# Database
DATABASE_URL=postgres://postgres:postgres@plausible_db:5432/plausible_db
CLICKHOUSE_DATABASE_URL=http://plausible_events_db:8123/plausible_events_db
# Email (optional, for notifications)
MAILER_EMAIL=plausible@yourdomain.com
SMTP_HOST_ADDR=smtp.yourdomain.com
SMTP_HOST_PORT=587
SMTP_USER_NAME=plausible@yourdomain.com
SMTP_USER_PWD=smtp-password
SMTP_HOST_SSL_ENABLED=false
SMTP_RETRIES=2
# Optional
DISABLE_REGISTRATION=true
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=Running the instance
# Download configuration files
git clone https://github.com/plausible/community-edition.git plausible
cd plausible
# Generate secret key
openssl rand -base64 64 | tr -d '\n'
# Edit plausible-conf.env with the generated key
# Start the services
docker compose up -d
# Check logs
docker compose logs -f plausible
# Plausible will be available at http://localhost:8000Nginx reverse proxy
# /etc/nginx/sites-available/plausible
server {
listen 80;
server_name analytics.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name analytics.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/analytics.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analytics.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location = /js/script.js {
proxy_pass http://127.0.0.1:8000/js/script.js;
proxy_set_header Host $host;
proxy_cache_valid 200 1h;
add_header Cache-Control "public, max-age=3600";
}
}Proxying the script through your own server
To avoid being blocked by ad blockers:
// app/api/script.js/route.ts (Next.js)
export async function GET() {
const response = await fetch('https://plausible.io/js/script.js')
const script = await response.text()
const modifiedScript = script.replace(
'https://plausible.io/api/event',
'https://yourdomain.com/api/event'
)
return new Response(modifiedScript, {
headers: {
'Content-Type': 'application/javascript',
'Cache-Control': 'public, max-age=3600'
}
})
}
// app/api/event/route.ts
export async function POST(request: Request) {
const body = await request.text()
await fetch('https://plausible.io/api/event', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': request.headers.get('user-agent') || '',
'X-Forwarded-For': request.headers.get('x-forwarded-for') || ''
},
body
})
return new Response('ok')
}Framework integrations
next-plausible
npm install next-plausible// app/layout.tsx
import PlausibleProvider from 'next-plausible'
export default function RootLayout({
children
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<head>
<PlausibleProvider
domain="yourdomain.com"
trackOutboundLinks
trackFileDownloads
taggedEvents
/>
</head>
<body>{children}</body>
</html>
)
}
'use client'
import { usePlausible } from 'next-plausible'
function MyComponent() {
const plausible = usePlausible()
const handleClick = () => {
plausible('Button Click', {
props: { location: 'header', variant: 'primary' }
})
}
return <button onClick={handleClick}>Click me</button>
}@plausible/tracker
npm install @plausible/tracker// lib/plausible.ts
import Plausible from '@plausible/tracker'
export const plausible = Plausible({
domain: 'yourdomain.com',
trackLocalhost: true,
apiHost: 'https://plausible.io'
})
import { plausible } from '@/lib/plausible'
plausible.trackEvent('Signup', {
props: { plan: 'pro' }
})
plausible.enableAutoPageviews()
plausible.enableAutoOutboundTracking()Vue.js plugin
// plugins/plausible.ts
import { createPlausible } from 'vue-plausible'
export default defineNuxtPlugin((nuxtApp) => {
const plausible = createPlausible({
domain: 'yourdomain.com',
trackLocalhost: false
})
nuxtApp.vueApp.use(plausible)
})
<script setup>
import { usePlausible } from 'vue-plausible'
const { trackEvent } = usePlausible()
function handleClick() {
trackEvent('Button Click')
}
</script>Plausible pricing
Plausible Cloud
| Pageviews / month | Monthly price | Annual price (discount) |
|---|---|---|
| 10,000 | $9 | $90 (17% off) |
| 100,000 | $19 | $190 (17% off) |
| 200,000 | $29 | $290 (17% off) |
| 500,000 | $49 | $490 (17% off) |
| 1,000,000 | $69 | $690 (17% off) |
| 2,000,000 | $89 | $890 (17% off) |
| 5,000,000 | $129 | $1,290 (17% off) |
| 10,000,000+ | Custom | Custom |
What every plan includes:
- Unlimited number of sites
- Unlimited team members
- All features (goals, funnels, custom events)
- Email reports
- API access
- Data export
- EU data hosting
Self-hosted
| Option | Cost |
|---|---|
| Community Edition | Free (AGPL) |
| Enterprise features | Commercial license |
Self-hosted requirements:
- 2GB RAM minimum
- 20GB disk (depends on traffic)
- Docker and Docker Compose
- Domain with SSL (Let's Encrypt)
FAQ - frequently asked questions
Does Plausible really not use cookies?
Yes, Plausible does not use any cookies or localStorage. Unique visit identification relies on hashing: IP + User Agent + domain + date. The hash is regenerated every day, so there is no way to track a user across days.
Do I need to display a GDPR banner?
No, if you are only using Plausible. Since Plausible does not collect personal data and does not use cookies, it does not require user consent under GDPR. However, if you use other tools that require consent, you will still need the banner.
How does Plausible handle ad blockers?
The default Plausible script is blocked by some ad blockers. Solutions:
- Proxy the script through your own server
- Use a custom subdomain (analytics.yourdomain.com)
- Self-host the entire instance
Can I use Plausible on multiple domains?
Yes, each domain is a separate "site" in the dashboard. You can also aggregate data from multiple subdomains on a single dashboard.
How long does Plausible store data?
Plausible Cloud stores data indefinitely -- there is no retention limit. In the self-hosted version, you can configure your own retention policies.
Does Plausible track subdomains?
You can configure Plausible to track:
- Only the main domain
- All subdomains together
- Each subdomain separately
<!-- All subdomains together -->
<script data-domain="yourdomain.com" src="..."></script>
<!-- Specific subdomain -->
<script data-domain="blog.yourdomain.com" src="..."></script>How to migrate from Google Analytics?
- Add the Plausible script alongside GA
- Compare data for 2-4 weeks
- Define goals matching your GA events
- Remove the GA script after verification
Plausible also offers historical data import from Google Analytics.
Can I use Plausible to track mobile apps?
Plausible is primarily designed for websites. For mobile apps, consider dedicated solutions like Mixpanel, Amplitude, or PostHog. However, you can use the Plausible API to send events from your application.