---
title: "PHP API Reference"
description: "The WPS facade, the trigger builder, the extension API, and every WordPress filter, action, and constant WordSocket exposes."
url: https://wpsignal.io/docs/php-api/
---

# PHP API Reference

The WPS facade, trigger builder, and WordPress filters exposed by the WordSocket plugin.

## WPS Facade

The `WPS` class is the main entry point. All methods are static. The class is a singleton; use `WPS::instance()` only when you need to access internal components directly.

### `WPS::instance()`

Get the singleton instance.

**Returns:** `WPS`

### `WPS::trigger($event)`

Create a new trigger builder. Returns a fluent builder: chain ->on(), ->channel(), ->data(), ->when(), then call ->register() to wire it up.

| Parameter | Type | Description |
| --- | --- | --- |
| $event | string | Event name (e.g. "post.updated", "comment.created"). |

**Returns:** `Trigger` A new trigger builder instance.

```php
WPS::trigger( 'user.login' )
    ->on( 'wp_login', 10, 2 )
    ->data( function ( $user_login, $user ) {
        return [ 'user_id' => $user->ID, 'login' => $user_login ];
    } )
    ->register();
```

### `WPS::publish($channel, $event, $data)`

Publish an event directly (no hook needed). Sends an HMAC-signed POST to the WPSignal server. The plugin must be configured (site\_key, site\_secret, base\_url) or this returns a WP\_Error.

| Parameter | Type | Description |
| --- | --- | --- |
| $channel | string | Channel name (e.g. "events"). Scoped server-side. |
| $event | string | Event name (e.g. "post.updated"). |
| $data | mixed | Arbitrary data (will be JSON-encoded). |

**Returns:** `array|WP_Error` wp\_remote\_post response array on success, WP\_Error on failure.

```php
WPS::publish( 'events', 'custom.event', [ 'key' => 'value' ] );
```

## Trigger Builder

`WPS::trigger($event)` returns a fluent builder. Chain the methods below and call `register()` to wire the WordPress hook.

Register triggers inside an `add_action('wpsignal_loaded', ...)` callback (in a plugin) or `add_action('init', ...)` (in a theme's functions.php).

### `->on( $hook, $priority, $accepted_args )`

Set the WordPress action hook to listen on.

| Parameter | Type | Description |
| --- | --- | --- |
| $hook | string | WordPress action hook name. |
| $priority | int | Optional. Hook priority. Default 10. |
| $accepted\_args | int | Optional. Number of hook arguments. Default 1. |

**Returns:** `$this`

```php
->on( 'save_post', 20, 3 )    // priority 20, 3 args
->on( 'wp_login' )            // defaults: priority 10, 1 arg
```

### `->channel( $channel )`

Set the channel to publish on. Defaults to "events" if not called. The server normalizes this to the full tenant-scoped channel name.

| Parameter | Type | Description |
| --- | --- | --- |
| $channel | string | Channel name. |

**Returns:** `$this`

```php
->channel( 'orders' )
```

### `->data( $callback )`

Set the data builder callback. The callback receives the same arguments as the WordPress hook and should return an associative array. This array becomes the \`data\` field in the published event payload.

| Parameter | Type | Description |
| --- | --- | --- |
| $callback | callable | Data builder. Receives hook args, returns array. |

**Returns:** `$this`

```php
->data( function ( $post_id, $post, $update ) {
    return [
        'post_id'    => $post_id,
        'post_title' => $post->post_title,
    ];
} )
```

### `->when( $callback )`

Set a condition callback. The callback receives the same arguments as the WordPress hook. Return false to skip publishing for this hook invocation. If not set, the trigger always fires.

| Parameter | Type | Description |
| --- | --- | --- |
| $callback | callable | Condition check. Receives hook args, returns bool. |

**Returns:** `$this`

```php
->when( function ( $post_id, $post ) {
    return 'publish' === $post->post_status;
} )
```

### `->register( )`

Register this trigger with the global trigger registry. This wires the WordPress hook so the trigger fires automatically. Must be called after configuring the builder.

## Extension API

The surface a plugin built on WordSocket uses. Reach each one from the singleton, for example `WPS::instance()->channels()`, inside an `add_action('wpsignal_loaded', ...)` callback.

### `WPS::instance()->channels()`

Reserve a channel namespace so only users passing a capability check may subscribe or publish. Reserving anything puts the site into strict mode, where channels that are not registered are refused.

### `->reserve( $ns, $grant, $publish )`

Reserve a namespace for users with a capability, or for whom a callable returns true.

| Parameter | Type | Description |
| --- | --- | --- |
| $ns | string | Namespace such as \`woo:orders\` (no \`site:\` prefix). A trailing colon is implied. |
| $grant | string\|callable | Who may subscribe: a capability name, or \`callable( int $user\_id ): bool\`. |
| $publish | string\|callable\|null | Who may publish and enter presence; defaults to \`$grant\`. |

### `->reservations( )`

Reserved namespaces with their grants.

**Returns:** `array<string,` string|callable>

### `->is_strict( )`

Whether any namespace is reserved (strict mode).

**Returns:** `bool`

### `->allowed_prefixes( $user_id, $site_id, $channels )`

Prefixes for a token.

| Parameter | Type | Description |
| --- | --- | --- |
| $user\_id | int | User the token is minted for (0 for visitors). |
| $site\_id | string | Hashed site identifier used in channel names. |
| $channels | string\[\] | Channels the client auto-subscribes to (after the \`wpsignal\_token\_channels\` filter). |

**Returns:** `string[]`

### `->allowed_publish_prefixes( $user_id, $site_id )`

Prefixes a token may publish on. Strict mode grants nothing by default: only reserved namespaces whose publish grant the user passes. Plugins add plain channels through the \`wpsignal\_token\_publish\_prefixes\` filter.

| Parameter | Type | Description |
| --- | --- | --- |
| $user\_id | int | User the token is minted for (0 for visitors). |
| $site\_id | string | Hashed site identifier used in channel names. |

**Returns:** `string[]`

### `WPS::instance()->extensions()`

Register a plugin built on WordSocket so it appears on the Extensions tab and nests under WordSocket on the Plugins screen.

### `->register( $slug, $args )`

Register an extension installed on this site.

| Parameter | Type | Description |
| --- | --- | --- |
| $slug | string | Plugin slug, for example \`shopsocket\`. |
| $args | array | Extension metadata: \`title\`, \`description\`, \`version\`, |

### `->registered( )`

Registered extensions.

**Returns:** `array<string,` array>

### `->all( )`

Everything the Extensions tab shows: registered extensions first, then catalogue entries not installed here.

**Returns:** `array<int,` array>

### `->plugin_files( )`

The plugin file of every extension WordSocket knows, registered or catalogued: what \`Plugins\_Screen\` matches the Plugins list against. A registered extension names its own file; everything else is assumed to sit where WordPress.org installs it, in a directory named after its slug.

**Returns:** `array<string,` string> Slug => plugin file.

### `WPS::instance()->publisher()`

HMAC-signed publishing to the relay, and the site’s own connection figures. Most code should call WPS::publish() rather than reaching for this directly.

### `->publish( $channel, $event, $data )`

Publish an event to the WPSignal server.

| Parameter | Type | Description |
| --- | --- | --- |
| $channel | string | Channel name (e.g. "events"). Scoped server-side. |
| $event | string | Event name (e.g. "post.updated"). |
| $data | mixed | Arbitrary data (will be JSON-encoded). |

**Returns:** `array|WP_Error` wp\_remote\_post response array on success, WP\_Error on failure.

```php
$publisher = WPS::instance()->publisher();
$publisher->publish( 'events', 'post.updated', [
    'post_id'    => 42,
    'post_title' => 'Hello World',
] );
```

### `->stats( )`

Ask the server about this site: browsers connected right now and the plan's connection limit. Signed like a publish over an empty body, so it needs no dashboard session. Extensions use it for "online now" figures.

**Returns:** `array{active_connections:` int, max\_connections: int}|\\WP\_Error

### `->remote_error( $response, $fallback )`

Turn a non-2xx server response into a \`WP\_Error\` carrying the server's own code (prefixed \`wpsignal\_\`) and message.

| Parameter | Type | Description |
| --- | --- | --- |
| $response | array | wp\_remote\_\* response. |
| $fallback | string | Code to use when the body has none. |

**Returns:** `WP_Error`

### `WPS::instance()->trigger_registry()`

Where registered triggers live once WPS::trigger(...)->register() has wired them, plus control over the built-in default trigger.

### `->add( $trigger )`

Add a trigger and wire its WordPress action hook.

| Parameter | Type | Description |
| --- | --- | --- |
| $trigger | Trigger | A configured trigger builder instance. |

### `->exclude_default_post_type( $post_type )`

Exclude a post type from the built-in default trigger. Called by Custom\_Triggers when registering a post-type trigger so the built-in save\_post handler skips that type (avoiding duplicate publishes).

| Parameter | Type | Description |
| --- | --- | --- |
| $post\_type | string | Post type slug. |

### `->get_excluded_default_post_types( )`

Get post types excluded from the built-in default trigger.

**Returns:** `string[]`

### `->all( )`

Return all registered triggers. Useful for inspection, debugging, and the Kitchen Sink triggers table.

**Returns:** `Trigger[]` Array of all registered trigger instances.

## WordPress Filters

Use `add_filter()` to hook into these.

### `wpsignal_token_channels`

Filters the channels the client auto-subscribes to on connect. Plugins can append their own channels so they are included in the initial WebSocket/SSE subscription without a separate subscribe call.

| Parameter | Type | Description |
| --- | --- | --- |
| $channels | string\[\] | Default channels for this site. |
| $user\_id | int | Current user ID. |
| $site\_id | string | Hashed site identifier from the JWT. |

```php
add_filter( 'wpsignal_token_channels', function ( $value ) {
    // modify $value and return it
    return $value;
} );
```

### `wpsignal_token_channel_prefixes`

Filters the channel prefixes the JWT allows the client to subscribe to. The WPSignal server rejects subscribe/publish frames whose channel does not start with one of these prefixes. The default is the site wildcard \`site:{site\_id}:\` until a plugin reserves a namespace through \`WPS::instance()->channels()->reserve()\`; from then on it is an explicit list (see \`Channels::allowed\_prefixes()\`), so register every channel you subscribe to through \`wpsignal\_token\_channels\`.

| Parameter | Type | Description |
| --- | --- | --- |
| $prefixes | string\[\] | Default allowed prefixes. |
| $user\_id | int | Current user ID. |
| $site\_id | string | Hashed site identifier from the JWT. |

```php
add_filter( 'wpsignal_token_channel_prefixes', function ( $value ) {
    // modify $value and return it
    return $value;
} );
```

### `wpsignal_token_publish_prefixes`

Filters the channel prefixes the JWT allows the client to publish on. Publishing covers \`WPS.publish()\`, binary frames, and presence. The default is the site wildcard until a plugin reserves a namespace; from then on only reserved namespaces whose publish grant the user passes (see \`Channels::reserve()\`), so a channel registered for reading stays read-only unless it is added here.

| Parameter | Type | Description |
| --- | --- | --- |
| $prefixes | string\[\] | Default publish prefixes. |
| $user\_id | int | Current user ID. |
| $site\_id | string | Hashed site identifier from the JWT. |

```php
add_filter( 'wpsignal_token_publish_prefixes', function ( $value ) {
    // modify $value and return it
    return $value;
} );
```

### `wpsignal_allow_client`

Controls whether the WordSocket client script is enqueued for the current request. Return \`false\` to prevent the script from loading (e.g. on specific post types or for guest users). Return \`true\` to force-load it regardless of login state.

| Parameter | Type | Description |
| --- | --- | --- |
| $allow | bool | Default: \`is\_user\_logged\_in()\`. |

```php
add_filter( 'wpsignal_allow_client', function ( $value ) {
    // modify $value and return it
    return $value;
} );
```

### `wpsignal_force_sse`

Forces the client to use SSE instead of WebSocket. Return \`true\` to disable WebSocket and fall back to Server-Sent Events. Useful in environments where WebSocket connections are blocked.

| Parameter | Type | Description |
| --- | --- | --- |
| $force | bool | Default: \`false\`. |

```php
add_filter( 'wpsignal_force_sse', function ( $value ) {
    // modify $value and return it
    return $value;
} );
```

### `wpsignal_encryption_seed`

Filters the seed used to derive the AES-256-GCM encryption key. The default seed is \`AUTH\_KEY . SECURE\_AUTH\_KEY\` from WordPress salts. Override this to supply your own key material without modifying WordPress salts.

| Parameter | Type | Description |
| --- | --- | --- |
| $seed | string | The default seed string. |

```php
add_filter( 'wpsignal_encryption_seed', function ( $seed ) {
    return 'my-application-specific-secret';
} );
```

## WordPress Actions

Use `add_action()` to hook into these.

### `wpsignal_loaded`

Fires when WPSignal is fully loaded and ready for trigger registration. NB: this can only be called by plugins since this runs on \`plugins\_loaded\` hook. Themes will need to use \`init\` hook instead. Third-party plugins should hook here to register custom triggers:

```php
add_action( 'wpsignal_loaded', function () {
    WPS::trigger( 'order.completed' )
        ->on( 'woocommerce_order_status_completed' )
        ->channel( 'orders' )
        ->data( function ( $order_id ) {
            $order = wc_get_order( $order_id );
            return [ 'order_id' => $order_id, 'total' => $order->get_total() ];
        } )
        ->register();
} );
```

## Constants

Define these in `wp-config.php` to override default plugin behaviour.

### `WPSignal\BASE_URL`

Define in wp-config.php to point the plugin at a self-hosted WPSignal server. When defined, overrides the default https://api.wpsignal.io endpoint for all publish, registration, and token requests.

```php
define( 'WPSignal\\BASE_URL', 'https://signal.example.com' );
```

### `WPSIGNAL_SITE_KEY`

Define in wp-config.php to hard-code the site key. Overrides the value stored in wp\_options by the auto-registration flow. Useful for environments where the database is ephemeral (e.g. CI, staging clones) or when credentials are managed via environment variables.

```php
const WPSIGNAL_SITE_KEY = 'your-32-char-hex-site-key';

// or using define:
define( 'WPSIGNAL_SITE_KEY', 'your-32-char-hex-site-key' );
```

### `WPSIGNAL_SITE_SECRET`

Define in wp-config.php to hard-code the publish secret. Overrides the value stored in wp\_options. Always pair with WPSIGNAL\_SITE\_KEY. Never expose this value to browsers.

```php
const WPSIGNAL_SITE_SECRET = 'your-64-char-hex-secret';

// or using define:
define( 'WPSIGNAL_SITE_SECRET', 'your-64-char-hex-secret' );
```

## Next steps

[

#### Getting Started

From a fresh WordPress install to live browser events in under 5 minutes.

](https://wpsignal.io/docs/getting-started/)[

#### JS API

Subscribe, publish, and handle events from the browser.

](https://wpsignal.io/docs/js-api/)[

#### Explorer

Interactive playground: connect, publish, and inspect events live.

](https://wpsignal.io/docs/explorer/)
