---
title: "Sites, goals & shared links — Plausible for Laravel | Roundly"
description: "Provision Plausible sites, conversion goals and shareable dashboard links from code — typed results, one rate-limit bucket."
url: https://roundly-consulting.com/open-source/docs/plausible-for-laravel/sites
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Plausible for Laravel](https://roundly-consulting.com/open-source/docs/plausible-for-laravel.md)

# Sites, goals & shared links

Provision analytics from code — handy for multi-tenant products that give each customer their own Plausible site. All three APIs share the sites rate-limit bucket.

## Sites

The Sites API is an Enterprise plan feature and needs a Sites API key — a Stats API key is refused there (see API keys under Configuration).

```php
use RoundlyConsulting\Plausible\Facades\Plausible;
use RoundlyConsulting\Plausible\Requests\Sites\CreateSiteRequest;
use RoundlyConsulting\Plausible\Requests\Sites\UpdateSiteRequest;

$site = Plausible::sites()->create(CreateSiteRequest::make(
    domain: 'my.domain.tld',
    timezone: 'Europe/Bratislava',                   // default 'Etc/UTC'
));                                                  // -> SiteResult

$site  = Plausible::sites()->get('my.domain.tld');   // -> SiteResult
$site->domain;                                       // 'my.domain.tld'
$site->timezone;                                     // 'Europe/Bratislava'
$site->data;                                         // the full payload

$sites = Plausible::sites()->list();                 // -> list<SiteResult>

Plausible::sites()->update(UpdateSiteRequest::make(
    site: 'my.domain.tld',                           // the current domain
    domain: 'new.domain.tld',                        // the new domain — the only field Plausible changes
));                                                  // -> SiteResult

UpdateSiteRequest::make(site: 'my.domain.tld', timezone: 'Europe/Prague');   // UnsupportedRequest — nothing is sent

$deleted = Plausible::sites()->delete('my.domain.tld');   // -> bool
```

create(), get(), list() and update() return typed SiteResult objects. Plausible’s Sites API can change a site’s domain but not its timezone, so UpdateSiteRequest throws UnsupportedRequest when given a timezone or no new domain, instead of sending a change Plausible would ignore. delete() returns true unless Plausible answers deleted: false, and a failed request throws. list() follows Plausible’s cursor pagination (meta.after, 100 per page) and returns every site. Site and goal ids are URL-encoded into the request path, so a value containing / or ? can’t reach another endpoint.

## Goals

Goals are part of the Sites API — an Enterprise plan feature that needs a Sites API key. CreateGoalRequest::event() creates a custom-event goal, ::page() a pageview goal, and list() walks every page:

```php
use RoundlyConsulting\Plausible\Requests\Sites\CreateGoalRequest;

$goal = Plausible::goals()->create(CreateGoalRequest::event('my-site.com', 'Signup'));  // -> GoalResult
Plausible::goals()->create(CreateGoalRequest::page('my-site.com', '/checkout'));

$goal->id;          // 42
$goal->goalType;    // 'event' or 'page'
$goal->eventName;   // 'Signup'
$goal->pagePath;    // null for event goals

$goals = Plausible::goals()->list('my-site.com');         // -> list<GoalResult>, every page
Plausible::goals()->delete('my-site.com', $goal->id);     // -> bool
```

## Shared links

Shared links are part of the Sites API too. create() is find-or-create — Plausible returns the existing link when one with that name exists — and the endpoint takes only a site and a name, so there is no password option:

```php
use RoundlyConsulting\Plausible\Requests\Sites\CreateSharedLinkRequest;

// Find-or-create: Plausible returns the existing link when one with that name exists
$link = Plausible::sharedLinks()->create('my-site.com', 'Public dashboard');  // -> SharedLinkResult
$link->name; // 'Public dashboard'
$link->url;  // shareable dashboard URL

// Or pass an explicit request object
Plausible::sharedLinks()->createFrom(CreateSharedLinkRequest::make('my-site.com', 'Board'));
```

## Tenant lifecycle

Put together, analytics can be ready on a tenant’s first day and gone when they leave:

```php
// Provision analytics when a tenant signs up …
Plausible::sites()->create(CreateSiteRequest::make(domain: $tenant->domain, timezone: $tenant->timezone));
Plausible::goals()->create(CreateGoalRequest::event($tenant->domain, 'Signup'));
$dashboard = Plausible::sharedLinks()->create($tenant->domain, 'Customer dashboard')->url;

// … and tear it down when they leave
Plausible::sites()->delete($tenant->domain);
```

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/plausible-for-laravel.md)
