---
sidebar_position: 1
---

# Getting started

The WordPlus realtime SDK gives any WordPress plugin, theme or custom code realtime features on a site with a WordPlus Cloud subscription:

- **Channels:** events from your server to browsers, and between browsers. See [channels](channels.md), [presence](presence.md), [publishing](publishing.md) and [client events](client-events.md).
- **Calls between two people:** they ring in the browser, run directly between the two browsers, and fall back to TURN, then to a media server, when the network needs it. See [calls](calls.md).
- **Group calls:** a room on WordPlus Cloud's media servers. See [group calls](group-calls.md).
- **A drop-in call screen:** a call button, a ring and a call window, with no JavaScript to write. See [the call screen](call-screen.md).
- **Encryption and WordPress's own users:** what you send is sealed with keys only the site and its users hold, and the site's users are one directory every plugin shares. See [encryption](encryption.md).

Everything rides the one connection a page shares with WordPlus's own plugins. That connection goes straight to a realtime server and moves to another one without a drop when a server restarts.

## 1. Install

```bash
composer require wordplus/realtime
```

Composer's autoloader includes `realtime.php`. Without Composer, unzip the package into your plugin, for example into its `vendor` folder, and require its `realtime.php` from your plugin's main file. Each version's zip is on [GitHub](https://github.com/wordplus-cloud/realtime-wordpress/releases) and [packages.wordplus.cloud](https://packages.wordplus.cloud/composer/wordplus-realtime-1.0.0.zip).

WordPlus mirrors every version on its own Composer repository. To install from there instead of Packagist, run `composer config repositories.wordplus composer https://packages.wordplus.cloud/composer` first.

Every plugin may bundle its own copy. The newest copy on the site answers `wordplus_realtime()`, and the newest connector serves every page, so plugins built on different versions work side by side. Call `wordplus_realtime()` from `plugins_loaded` on.

## 2. The site's credentials

The SDK works on a site that has its WordPlus Cloud credentials: a site key and a secret. Every WordPlus plugin on the site shares them in the option `wordplus_cloud_license`.

- **A site running a WordPlus plugin** (Better Messages, for example) has them once its licence is active.
- **Any other site** connects once, from your plugin's settings page:

```php
if ( ! wordplus_realtime()->available() ) {
	printf(
		'<a class="button" href="%s">%s</a>',
		esc_url( wordplus_realtime()->connect()->url( admin_url( 'admin.php?page=my-plugin' ) ) ),
		esc_html__( 'Connect to WordPlus Cloud', 'my-plugin' )
	);
}
```

The administrator approves in their WordPlus Cloud account, which uses one of their subscription's sites. They come back to your page with `wordplus_realtime=connected`, or `denied` or `failed`.

The secret never leaves the site's server, and it signs nothing itself. Tokens, publishes and calls each use their own key derived from it.

**Only the site's own pages connect.** A page on another address, a subdomain included, is refused with `wrong_origin`. So neither the site's key, which every page carries, nor its secret works on another website.

## 3. A first channel

Own the channels whose names start with your prefix, and say who may join them:

```php
add_action( 'plugins_loaded', function () {
	wordplus_realtime()->channel( 'private-orders-', function ( $user_id, $channel ) {
		$order = (int) substr( $channel, strlen( 'private-orders-' ) );
		return $user_id > 0 && my_shop_customer_of( $order ) === $user_id;
	} );
} );
```

Send an event from your server:

```php
wordplus_realtime()->publish( 'private-orders-42', 'updated', array( 'status' => 'paid' ) );
```

Listen in the browser. Your script depends on the SDK's handle:

```php
wp_enqueue_script( 'my-shop', plugins_url( 'shop.js', __FILE__ ), array( wordplus_realtime()->script() ), '1.0.0', true );
```

```js
// Unset on a site without its credentials: there is nothing to listen to there.
if ( window.wordplusRealtimeConfig ) {
	const rt = wordplusRealtimeClient.channels( window.wordplusRealtimeConfig );

	rt.subscribe( 'private-orders-42' ).on( 'updated', ( data ) => showStatus( data.status ) );
}
```

`script()` always returns a handle. On a site without credentials it returns an empty one, so your script still loads and simply finds `window.wordplusRealtimeConfig` unset.

## 4. A first call

Own the calls whose names start with your prefix:

```php
add_action( 'plugins_loaded', function () {
	wordplus_realtime()->calls( 'support-', function ( $user_id, $call, $with ) {
		return my_support_may_call( $user_id, $call, $with );
	} );
} );

add_action( 'wp_enqueue_scripts', function () {
	if ( is_user_logged_in() ) {
		wordplus_realtime()->call_screen();
	}
} );
```

Put a call button on a page:

```html
<wordplus-call to="34" call="support-42" type="video" name="Ann">Call Ann</wordplus-call>
```

User 34's every open page that loads the call screen rings. When they accept, the call window opens on both sides. [calls.md](calls.md) explains the callback, and [call-screen.md](call-screen.md) the elements.

## What it needs

- **WordPlus Cloud:** a subscription that includes realtime (channels) and calls. Without them the connection is refused with `not_included`.
- **PHP** 7.4 or newer.
- **Browsers:** any current browser. Calls need WebRTC, which every current browser has.

## Next

- Look at a complete plugin: `examples/live-comments` (channels and presence) and `examples/video-support` (calls, group calls and the call screen).
- Coding with an AI agent? Point it at `skills/wordplus-realtime`.
