Sites

Manage your websites and analytics properties

Overview

The Sites API allows you to create, list, update, and delete websites (analytics properties) in your Zero Trust Analytics account. Each site has a unique ID used for tracking and data retrieval.

Endpoints

GET    /api/sites          # List all sites
POST   /api/sites          # Create a new site
PATCH  /api/sites          # Update a site
POST   /api/sites/delete   # Delete a site (soft delete)
GET    /api/sites/deleted  # List deleted sites
POST   /api/sites/restore  # Restore a deleted site

Requires authentication. See Authentication.

List Sites

Get all sites in your account.

Request

curl "https://ztas.io/api/sites" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

{
  "sites": [
    {
      "id": "site_abc123",
      "domain": "example.com",
      "name": "Example Website",
      "timezone": "America/New_York",
      "public": false,
      "createdAt": "2024-01-15T10:00:00.000Z",
      "stats": {
        "pageviews": 125432,
        "visitors": 45231,
        "lastPageview": "2024-12-12T16:30:00.000Z"
      },
      "teamMembers": 3
    },
    {
      "id": "site_def456",
      "domain": "blog.example.com",
      "name": "Example Blog",
      "timezone": "America/Los_Angeles",
      "public": true,
      "createdAt": "2024-03-20T14:00:00.000Z",
      "stats": {
        "pageviews": 87654,
        "visitors": 32145,
        "lastPageview": "2024-12-12T16:25:00.000Z"
      },
      "teamMembers": 2
    }
  ]
}

Create Site

Add a new website to track analytics.

Request

curl -X POST "https://ztas.io/api/sites" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "newsite.com",
    "name": "New Site",
    "timezone": "America/New_York",
    "public": false
  }'

Parameters

ParameterTypeRequiredDescription
domainstringYesWebsite domain (without protocol)
namestringNoFriendly name for the site (defaults to domain)
timezonestringNoTimezone for date/time display (default: UTC)
publicbooleanNoMake stats publicly viewable (default: false)

Domain Format

Domains should be provided without protocol or path:

✅ Good:

  • example.com
  • www.example.com
  • blog.example.com

❌ Bad:

  • https://example.com
  • example.com/
  • example.com/blog

Timezone

Use IANA timezone identifiers:

  • America/New_York
  • America/Los_Angeles
  • America/Chicago
  • Europe/London
  • Europe/Paris
  • Asia/Tokyo
  • UTC

Full list of timezones

Response

{
  "site": {
    "id": "site_abc123",
    "domain": "newsite.com",
    "name": "New Site",
    "timezone": "America/New_York",
    "public": false,
    "createdAt": "2024-12-12T16:00:00.000Z",
    "trackingCode": "<script async src=\"https://cdn.ztas.io/track.js\" data-site-id=\"site_abc123\"></script>"
  }
}

Important: Save the trackingCode - you’ll need to add it to your website to start collecting analytics.

Update Site

Modify site settings.

Request

curl -X PATCH "https://ztas.io/api/sites" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "site_abc123",
    "name": "Updated Name",
    "timezone": "America/Los_Angeles",
    "public": true
  }'

Parameters

ParameterTypeRequiredDescription
idstringYesSite ID to update
namestringNoNew site name
timezonestringNoNew timezone
publicbooleanNoChange public visibility

Note: You cannot change the domain after creation. Delete and recreate the site if needed.

Response

{
  "site": {
    "id": "site_abc123",
    "domain": "example.com",
    "name": "Updated Name",
    "timezone": "America/Los_Angeles",
    "public": true,
    "updatedAt": "2024-12-12T16:00:00.000Z"
  }
}

Delete Site

Delete a site (soft delete with recovery period).

Request

curl -X POST "https://ztas.io/api/sites/delete" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId": "site_abc123"}'

Parameters

ParameterTypeRequiredDescription
siteIdstringYesSite ID to delete

Response

{
  "success": true,
  "softDeleted": true,
  "expiresAt": "2026-01-14T22:15:00.000Z",
  "retentionDays": 3,
  "message": "Site moved to trash. You can restore it within 3 days."
}

Recovery Window by Plan

Sites are soft-deleted and can be recovered within a plan-based retention period:

PlanRecovery Window
Free3 days
Starter7 days
Growth14 days
Business30 days
Scale30 days
Enterprise30 days

After the recovery window expires, the site and all its data are permanently deleted.


List Deleted Sites

Get all soft-deleted sites that can still be recovered.

Request

curl "https://ztas.io/api/sites/deleted" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

{
  "sites": [
    {
      "id": "site_abc123",
      "name": "Example Website",
      "domain": "example.com",
      "deletedAt": "2026-01-11T22:15:00.000Z",
      "expiresAt": "2026-01-14T22:15:00.000Z",
      "daysRemaining": 3
    }
  ],
  "count": 1
}

Restore Site

Restore a soft-deleted site before it expires.

Request

curl -X POST "https://ztas.io/api/sites/restore" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId": "site_abc123"}'

Parameters

ParameterTypeRequiredDescription
siteIdstringYesSite ID to restore

Response

{
  "success": true,
  "restored": true,
  "site": {
    "id": "site_abc123",
    "name": "Example Website",
    "domain": "example.com"
  }
}

Error Responses

{
  "error": "Site recovery period has expired"
}
{
  "error": "Site not found or not deleted"
}

Get Site Details

Get detailed information about a specific site.

Request

curl "https://ztas.io/api/sites/site_abc123" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

{
  "site": {
    "id": "site_abc123",
    "domain": "example.com",
    "name": "Example Website",
    "timezone": "America/New_York",
    "public": false,
    "createdAt": "2024-01-15T10:00:00.000Z",
    "owner": {
      "id": "user_abc123",
      "email": "owner@example.com",
      "name": "Alice Johnson"
    },
    "stats": {
      "pageviews": 125432,
      "visitors": 45231,
      "sessions": 67543,
      "bounceRate": 42.5,
      "avgSessionDuration": 185,
      "lastPageview": "2024-12-12T16:30:00.000Z"
    },
    "team": [
      {
        "id": "user_abc123",
        "email": "owner@example.com",
        "role": "owner"
      },
      {
        "id": "user_def456",
        "email": "admin@example.com",
        "role": "admin"
      }
    ],
    "goals": 5,
    "funnels": 2,
    "alerts": 3
  }
}

Public Sites

Make your analytics data publicly viewable:

curl -X PATCH "https://ztas.io/api/sites" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "site_abc123",
    "public": true
  }'

When public is true:

  • Anyone can view analytics at https://ztas.io/public/site_abc123
  • No authentication required
  • Read-only access
  • Great for open-source projects and transparency

Public dashboard URL: https://ztas.io/public/{siteId}

Tracking Code

After creating a site, add the tracking code to your website:

Standard Installation

Add before the closing </head> tag:

<!DOCTYPE html>
<html>
<head>
  <title>My Website</title>
  <!-- Zero Trust Analytics -->
  <script async src="https://cdn.ztas.io/track.js" data-site-id="site_abc123"></script>
</head>
<body>
  <!-- Your content -->
</body>
</html>

Next.js

Add to pages/_app.js or app/layout.js:

import Script from 'next/script'

export default function App({ Component, pageProps }) {
  return (
    <>
      <Script
        src="https://cdn.ztas.io/track.js"
        data-site-id="site_abc123"
        strategy="afterInteractive"
      />
      <Component {...pageProps} />
    </>
  )
}

React

Add to your main component:

import { useEffect } from 'react';

function App() {
  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://cdn.ztas.io/track.js';
    script.setAttribute('data-site-id', 'site_abc123');
    script.async = true;
    document.head.appendChild(script);
  }, []);

  return <div>Your app</div>;
}

WordPress

Add to your theme’s header.php before </head>:

<script async src="https://cdn.ztas.io/track.js" data-site-id="site_abc123"></script>
<?php wp_head(); ?>

Or use the Zero Trust Analytics WordPress plugin.

Site Limits

PlanMax Sites
Free3
Pro10
Business50
EnterpriseUnlimited

Site Settings

Exclude Paths

Exclude certain paths from tracking:

curl -X PATCH "https://ztas.io/api/sites" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "site_abc123",
    "settings": {
      "excludePaths": ["/admin", "/dashboard"]
    }
  }'

Ignore Query Parameters

Ignore specific query parameters in URLs:

curl -X PATCH "https://ztas.io/api/sites" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "site_abc123",
    "settings": {
      "ignoreParams": ["utm_source", "utm_medium", "fbclid"]
    }
  }'

Data Retention

Configure how long to keep analytics data:

curl -X PATCH "https://ztas.io/api/sites" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "site_abc123",
    "settings": {
      "dataRetention": 365
    }
  }'
PlanDefault RetentionMax Retention
Free90 days90 days
Pro1 year2 years
Business2 years5 years
Enterprise2 yearsUnlimited

Data Export

Export all site data before deleting:

curl "https://ztas.io/api/sites/site_abc123/export" \
  -H "Authorization: Bearer YOUR_TOKEN"

Returns a download URL for a ZIP file containing:

  • All pageview data (CSV)
  • Custom events (CSV)
  • Goals and funnels (JSON)
  • Site settings (JSON)

See Export API for more details.

Verify Domain Ownership

For certain features (custom domains, SSO), you may need to verify domain ownership:

curl "https://ztas.io/api/sites/site_abc123/verify" \
  -H "Authorization: Bearer YOUR_TOKEN"

Returns a TXT record to add to your DNS:

{
  "verification": {
    "type": "TXT",
    "name": "_zta-verify",
    "value": "zta-verify=abc123def456"
  }
}

Add this TXT record to your DNS, then verify:

curl -X POST "https://ztas.io/api/sites/site_abc123/verify" \
  -H "Authorization: Bearer YOUR_TOKEN"

Error Responses

400 Bad Request

{
  "error": "Domain is required"
}
{
  "error": "Invalid domain format"
}
{
  "error": "Invalid timezone"
}

403 Forbidden

{
  "error": "Site limit reached. Upgrade to create more sites."
}
{
  "error": "Only the site owner can delete this site"
}

404 Not Found

{
  "error": "Site not found"
}

409 Conflict

{
  "error": "A site with this domain already exists"
}

Best Practices

1. Use Descriptive Names

Make it easy to identify sites:

✅ Good: “Marketing Website”, “Product Documentation”, “Blog” ✗ Bad: “Site 1”, “Test”, “ABC”

2. Set the Correct Timezone

Match your business timezone for accurate daily reports:

{
  "timezone": "America/New_York"  # If your team is in NYC
}

3. One Site Per Domain

Create separate sites for:

  • example.com (main site)
  • blog.example.com (blog)
  • app.example.com (application)

Don’t combine them into one site unless they share the same navigation.

4. Use Public Sites for Transparency

Show your metrics publicly:

{
  "public": true
}

Great for:

  • Open-source projects
  • Transparency initiatives
  • Building trust

5. Configure Exclusions Early

Exclude admin and internal pages:

{
  "settings": {
    "excludePaths": ["/admin", "/dashboard", "/internal"]
  }
}

6. Test Tracking Before Launch

Verify tracking works:

# Send a test pageview
curl -X POST "https://ztas.io/api/track" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "pageview",
    "siteId": "site_abc123",
    "path": "/test"
  }'

# Check realtime stats
curl "https://ztas.io/api/realtime?siteId=site_abc123" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example: Multi-Site Management

Manage multiple client sites:

const API_KEY = 'zta_live_abc123...';

// Create sites for all clients
const clients = [
  { domain: 'client1.com', name: 'Client 1' },
  { domain: 'client2.com', name: 'Client 2' },
  { domain: 'client3.com', name: 'Client 3' }
];

for (const client of clients) {
  const response = await fetch('https://ztas.io/api/sites', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      domain: client.domain,
      name: client.name,
      timezone: 'America/New_York'
    })
  });

  const data = await response.json();
  console.log(`Created site for ${client.name}: ${data.site.id}`);
}

// List all sites
const sitesResponse = await fetch('https://ztas.io/api/sites', {
  headers: { 'Authorization': `Bearer ${API_KEY}` }
});

const sites = await sitesResponse.json();
console.log(`Total sites: ${sites.sites.length}`);

Example: Site Backup

Backup all site configurations:

import requests
import json

API_KEY = 'zta_live_abc123...'

# Get all sites
response = requests.get(
    'https://ztas.io/api/sites',
    headers={'Authorization': f'Bearer {API_KEY}'}
)

sites = response.json()['sites']

# Save to file
with open('sites_backup.json', 'w') as f:
    json.dump(sites, f, indent=2)

print(f"Backed up {len(sites)} sites")