WP WordPress Intermediate

DataFirefly Native Live Shopping — Documentation

Full guide to the self-hosted WebRTC live shopping plugin for WooCommerce: install, host console, settings, replay, REST hooks and troubleshooting.

Updated Module version 1.0.0

Overview

DataFirefly Native Live Shopping turns your WooCommerce store into a self-hosted live shopping platform, with no dependency on third-party services like Bambuser or CommentSold. Broadcasting uses WebRTC peer-to-peer mesh from the host’s browser to each viewer, signaling goes through the WordPress REST API, and replay recording is done client-side via the MediaRecorder API then stored as WordPress attachments.

The plugin provides:

  • A dfnls_live_show CPT to create and schedule your live shows
  • A host console embedded in the WordPress admin (camera preview, controls, products, chat)
  • A turnkey viewer experience with clickable products in overlay and chat
  • A WooCommerce cart bridge (add to the official cart without leaving the live)
  • Automatic replay synchronized with live events (spotlights, coupons, messages)
  • A dedicated Gutenberg block and the [dfnls_live] shortcode
Architecture — The WebRTC mesh topology is ideal up to ~25 simultaneous viewers per host. Beyond that, plan an external TURN server or consider an SFU. The host’s upload bandwidth should be around 500 kbps per connected viewer.

Requirements

  • WordPress 6.3 or higher
  • WooCommerce 8.0 or higher (HPOS compatible)
  • PHP 8.1 or higher (tested up to 8.3)
  • HTTPS requiredgetUserMedia() and getDisplayMedia() refuse to work over non-secure HTTP
  • Supported browsers on the viewer side: Chrome 80+, Firefox 75+, Edge 80+, Safari 14+, Opera 67+
  • A recent browser on the host side with accessible camera and microphone
Important — Without a valid HTTPS certificate (Let’s Encrypt is enough), the host console cannot access camera or microphone. Test on localhost or on a domain with a TLS certificate.

Installation

  1. Download the df-native-live-shopping.zip archive from your DataFirefly account.
  2. In WordPress, go to Plugins → Add NewUpload Plugin.
  3. Select the ZIP file and click Install Now.
  4. Once installed, click Activate Plugin.
  5. A new Live Shopping menu appears in the admin sidebar.

On activation, the plugin:

  • Creates 5 custom tables (wp_dfnls_signaling, _sessions, _events, _replay_parts, _chat)
  • Adds the manage_dfnls_lives and host_dfnls_lives capabilities to the administrator and shop_manager roles
  • Schedules two crons: daily purge of old replays, hourly purge of stale signaling messages
  • Registers default options (Google STUN servers, 90-day retention, 25 viewers max, etc.)

First live in 5 minutes

The shortest path to launch your first live show:

  1. Live Shopping → New live menu
  2. Enter a title (e.g. “Spring flash sale”)
  3. In the Products metabox, search and select the WooCommerce products you want to showcase (drag and drop to reorder)
  4. Optional: in Scheduling, set a start date and time (a countdown will display on the viewer side)
  5. Publish the live
  6. Go to Live Shopping → Host console and select your live
  7. Click Start broadcast, allow camera and microphone access
  8. Share the public URL of the live (/live/your-slug/) with your audience

Host console

The host console is the dashboard from which you moderate your live. It’s accessible via Live Shopping → Host console. Features:

Video preview and controls

  • Camera: toggles camera activation/deactivation
  • Microphone: toggles microphone activation/deactivation
  • Screen share: replaces the camera stream with a screen share (useful for demos)
  • Start / Stop: main live control buttons

Product spotlighting

The list of products linked to the live displays on the right. Each product has a Spotlight button. Clicking it:

  • Immediately shows the product overlay to all viewers
  • Records a timestamped product.spotlight event for replay sync
  • A second click on the same button removes the overlay

Coupon broadcasting

Enter a promo code (e.g. LIVE20) and optionally a description, then click Broadcast. An animated flash appears on the viewers’ screen with a “Copy” button to grab the code in one click.

Host messages

A free-text input lets you send a message that displays as a temporary banner on the viewer side (8 seconds by default).

Live chat

Host/viewer chat is integrated into the console. Host messages are visually distinguished (badge and red border) in all views.

Activity log

A log at the bottom of the console displays in real time connections/disconnections, broadcast events, replay chunk uploads, and any errors.

Viewer experience

What the audience sees on the public URL of the live:

  • Before the live — If the live is scheduled, a waiting screen displays with a countdown until the planned time. Auto-poll of the status every 5 seconds to detect the start.
  • During the live — Live video with a pulsing “LIVE” pill and viewer counter. Sidebar with two tabs: Products (clickable list of live products) and Chat.
  • Product overlay — When the host spotlights a product, a card slides in (default: bottom right) with photo, name, price and Add to cart button.
  • Add to cart — One click on the button adds the product to the official WooCommerce cart. A FAB (floating button) appears at the bottom right with the cart item counter.
  • Coupon flash — Broadcast by the host, displays at the top with animation and copy button.
  • After the live — If replay is enabled, a “Watch replay” button lets you replay the live with full event synchronization.

Global settings

Live Shopping → Settings menu. Main sections:

STUN servers

By default, Google’s public STUN servers are used:

stun:stun.l.google.com:19302
stun:stun1.l.google.com:19302

You can add your own STUN servers (one per line).

TURN servers

Optional but recommended for viewers behind symmetric NAT (some 4G carriers, corporate VPNs). Format:

turn:turn.example.com:3478
turns:turn.example.com:5349

Enter the associated TURN username and TURN credential.

Recording and replay

  • Recording enabled: global yes / no
  • Chunk duration (ms): 5000 by default. Shorter = more crash resilience but more requests; longer = fewer requests but more loss on crash
  • Replay retention (days): 90 by default. Beyond that, the daily cron automatically deletes WebM files and related entries

Capacity and overlay

  • Max viewers per host: 25 by default. Adjust to your upload bandwidth
  • Overlay position: right, left or bottom

Per-live defaults

  • Chat enabled by default
  • Replay enabled by default
  • Login required by default

STUN and TURN servers — when to configure a TURN

STUN is a simple public IP discovery server, free and sufficient in ~85% of cases. TURN, on the other hand, actually relays media traffic: it consumes bandwidth, but allows connecting two clients that cannot directly reach each other.

Configure a TURN if:

  • Your viewers regularly complain about not seeing the video (WebRTC connection state stuck at “connecting”)
  • Your audience contains many 4G/5G mobile users with symmetric NAT carriers (Free Mobile in France notably)
  • Your host or viewers are behind a strict corporate VPN
Recommended solution — Deploying a self-hosted coturn on a small VPS (€5-10 / month) is enough for 30-40 concurrent viewers. Paid alternatives: Xirsys, Twilio Network Traversal Service.

Recording and replay

How recording works

Recording happens entirely on the host’s browser side via the MediaRecorder API:

  1. At live start, MediaRecorder is instantiated with automatic detection of the best available codec (VP9 > VP8 > H.264, opus for audio, ~1.5 Mbps video + 96 kbps audio)
  2. Every 5 seconds (configurable), a WebM chunk is triggered and uploaded via POST /wp-json/df-nls/v1/shows/{id}/replay/chunk
  3. The chunk is stored as a WordPress attachment, named dfnls-show-{id}-part-{NNNNN}.webm, with post_parent pointing to the live
  4. The wp_dfnls_replay_parts table keeps the order and duration of each chunk

How replay works

On page load in replay mode:

  1. The viewer calls GET /wp-json/df-nls/v1/shows/{id}/replay which returns the ordered list of segments and the events timeline
  2. Segments are loaded sequentially via the ended event of the <video> element (native fallback)
  3. A MediaSource variant enables transparent concatenation if the browser supports it
  4. The playback position (cumulative time) is compared to each event’s offset_ms — when the point is crossed, the viewer locally triggers the same behavior as in live (show overlay, coupon flash, message)

Storage and disk space

Order of magnitude: a one-hour live at 1.5 Mbps video + 96 kbps audio produces about 720 MB of WebM files. With 90-day retention and 4 lives per month, count ~10 GB of disk space dedicated to replays.

MIME and upload — The plugin adds an upload_mimes filter to allow video/webm and video/mp4 from the media library. Check that your server doesn’t have overly strict LimitRequestBody or upload_max_filesize rules (target 20 MB minimum per chunk).

Integration: shortcode, block, direct URL

Direct public URL

Each published live has its own automatically generated URL:

https://your-site.com/live/your-slug/

This is the simplest way: share this link with your audience.

Shortcode

To insert a live into an existing page or post:

[dfnls_live id="42"]
[dfnls_live id="42" mode="live"]
[dfnls_live id="42" mode="replay"]
[dfnls_live id="42" mode="auto"]

Available modes:

  • auto (default): detects the live status and displays live / waiting / replay accordingly
  • live: forces live broadcast display (useful for testing)
  • replay: forces replay mode even if the live is still in progress

Gutenberg block

In the block editor, search for “Live Shopping”. The block supports wide and full alignments, exposes a selector to choose the live and a mode selector in the inspector sidebar.

Custom PHP template

The CPT uses templates/single-live-show.php. To override, copy this file into your theme under your-theme/df-native-live-shopping/single-live-show.php.

Multilingual with Polylang

The plugin declares the dfnls_live_show CPT as translatable with Polylang. On activation, if Polylang is already installed:

  • Each live can have an FR, EN, ES, DE, IT version, etc.
  • Critical metadata (_dfnls_product_ids, _dfnls_scheduled_at, live options) is copied automatically between translations
  • The 5 integrated languages (FR, EN, ES, DE, IT) are loaded automatically according to the WordPress locale
Polylang Pro tip — If you use Polylang Pro and your WooCommerce products are themselves translated, each live translation must be associated with the corresponding language version of the products. The plugin does not perform automatic cross-language mapping on product IDs.

HPOS and compatibilities

The plugin officially declares compatibility with WooCommerce’s high-performance order storage (HPOS) via FeaturesUtil. You can enable HPOS on your installation without risk of the cart bridge malfunctioning.

Also compatible with:

  • WordPress Multisite (per-site install, no network mode)
  • Shared hosting (o2switch, OVH, Infomaniak, PlanetHoster) — signaling uses REST polling, no WebSocket
  • Cache plugins (WP Rocket, WP Super Cache) — plugin REST endpoints are automatically excluded

Security and capabilities

The plugin adds two dedicated capabilities:

  • manage_dfnls_lives — create, edit, delete lives; access to settings
  • host_dfnls_lives — access to the host console, start / stop a live

Both capabilities are assigned by default to the administrator and shop_manager roles. To grant a user only the right to host without being able to create lives:

$user = get_user_by('login', 'presenter');
$user->add_cap('host_dfnls_lives');

REST nonces

All action routes (POST) are protected by wp_rest nonce. The viewer and host receive their respective nonce via wp_localize_script at page load.

Upload MIME validation

Replay chunk uploads are strictly validated via wp_check_filetype_and_ext to accept only video/webm and video/mp4. Files are renamed server-side (dfnls-show-{id}-part-{NNNNN}.webm).

Cron and maintenance

Two WordPress crons are scheduled on activation:

  • dfnls_cleanup_expired_replaysdaily. Deletes replays of lives ended more than N days ago (configurable retention). Uses wp_delete_attachment(..., true) to also remove the physical file.
  • dfnls_cleanup_stale_signalinghourly. Purges signaling messages older than 24h and sessions inactive for more than 90 seconds.
WP-Cron disabled — If you’ve disabled WP-Cron in favor of a system cron, make sure to call wp-cron.php at least once per hour so purges execute.

For developers — REST API

All routes are under the df-nls/v1 namespace.

Show

  • GET /shows/{id} — fetches a live (status, products, options)
  • POST /shows/{id}/join — joins as viewer or host (body: peer_id, role)
  • POST /shows/{id}/leave — cleanly leaves
  • POST /shows/{id}/heartbeat — keeps the session open (auto every 15s on viewer side)
  • POST /shows/{id}/start — starts the live (host only)
  • POST /shows/{id}/end — ends the live (host only)
  • GET /shows/{id}/viewers — active viewer counter

WebRTC Signaling

  • POST /signal/send — sends an SDP/ICE message to a remote peer
  • GET /signal/pull?peer={id} — retrieves pending messages and performs an implicit heartbeat

Events

  • POST /shows/{id}/event — records an event (spotlight, message, coupon)
  • GET /shows/{id}/events?since={id} — pull events since a given ID

Chat

  • GET /shows/{id}/chat?since={id} — pull messages since an ID
  • POST /shows/{id}/chat — send a message

Cart bridge

  • POST /cart/add — adds a product to the cart with source tracking (show_id, product_id, quantity)
  • GET /cart/summary — current cart counter and total

Recording and replay

  • POST /shows/{id}/replay/chunk — multipart upload of a WebM chunk
  • GET /shows/{id}/replay — segments + timeline events for playback

Plugin structure (PSR-4)

df-native-live-shopping/
├── df-native-live-shopping.php        # Bootstrap
├── uninstall.php
├── readme.txt
├── assets/
│   ├── js/    (host.js, viewer.js, admin.js, block-editor.js)
│   └── css/   (host.css, viewer.css, admin.css)
├── languages/                          # 5 .po/.mo + .pot
├── templates/                          # single-live-show.php, viewer-container.php, ...
└── src/
    ├── Plugin.php
    ├── Activator.php   Deactivator.php
    ├── PostType/       (LiveShow.php)
    ├── Database/       (Schema + 5 Repository.php)
    ├── Admin/          (AdminPages, MetaBoxes, SettingsPage)
    ├── Api/            (RestController, SignalingController, CartController)
    ├── Recording/      (RecordingHandler)
    ├── Replay/         (ReplayHandler)
    ├── Frontend/       (Renderer, Shortcode, Block)
    └── Compat/         (PolylangCompat)

Root namespace: DataFirefly / NativeLiveShopping, manual PSR-4 autoloader declared in df-native-live-shopping.php.

Troubleshooting

Viewers don’t see the video

  • Verify the site is on HTTPS (mandatory for WebRTC)
  • Open the browser console on the viewer side, look for ICE failed or connection state failed errors
  • Configure a TURN server if the audience contains many 4G mobiles
  • Verify that the host’s upload bandwidth is sufficient (fast.com utility on the host side)

The host console doesn’t detect the camera

  • Verify the browser has granted permission (padlock icon in the URL bar)
  • On macOS, check system permissions: Preferences → Security → Camera
  • Close other applications using the camera (Zoom, Teams, OBS…)

Replay chunks are not uploading

  • Check upload_max_filesize and post_max_size in php.ini (target 20 MB minimum)
  • Check LimitRequestBody on Apache side if applicable
  • Look at the host console activity log to identify the exact error
  • Check the wp-content/uploads folder permissions

Cart doesn’t retain additions

  • Verify no cache plugin caches the /wp-json/df-nls/v1/* endpoints
  • Verify WooCommerce cookies (woocommerce_cart_hash, wp_woocommerce_session_*) are properly emitted
  • On strict HTTPS, verify cookies have the Secure flag

Replays take too much space

  • Reduce retention (e.g. from 90 to 30 days) in settings
  • Disable recording for lives where it’s not necessary (“Allow replay” checkbox in Options metabox)
  • Reduce bitrate by modifying host.js (variable videoBitsPerSecond)

Uninstallation

On simple deactivation, data is preserved and crons are unscheduled. On full deletion of the plugin from Plugins, uninstall.php performs:

  • Removal of the 5 custom tables
  • Removal of all dfnls_* options
  • Removal of capabilities from roles
  • Unscheduling of crons
  • Optional: removal of CPTs and all replay attachments if the dfnls_uninstall_delete_data option was enabled before uninstallation
Warning — By default, lives and their replays are NOT deleted on uninstallation. To delete everything, enable the Delete all data on uninstall option in settings before uninstalling.

Support and roadmap

Technical support included for 12 months via the DataFirefly customer area. Plugin updates are available from your account, with email notification for major versions.

Roadmap ideas:

  • Automatic SFU switching beyond a viewer threshold
  • Live polls (poll.open / poll.close already reserved in the event protocol)
  • Native analytics (average watch time, conversion rate per live)
  • Multi-host support (two concurrent presenters)
Was this page helpful?

Still stuck? Contact support