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.
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_showCPT 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
Requirements
- WordPress 6.3 or higher
- WooCommerce 8.0 or higher (HPOS compatible)
- PHP 8.1 or higher (tested up to 8.3)
- HTTPS required —
getUserMedia()andgetDisplayMedia()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
localhost or on a domain with a TLS certificate.
Installation
- Download the
df-native-live-shopping.ziparchive from your DataFirefly account. - In WordPress, go to Plugins → Add New → Upload Plugin.
- Select the ZIP file and click Install Now.
- Once installed, click Activate Plugin.
- 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_livesandhost_dfnls_livescapabilities to theadministratorandshop_managerroles - 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:
- Live Shopping → New live menu
- Enter a title (e.g. “Spring flash sale”)
- In the Products metabox, search and select the WooCommerce products you want to showcase (drag and drop to reorder)
- Optional: in Scheduling, set a start date and time (a countdown will display on the viewer side)
- Publish the live
- Go to Live Shopping → Host console and select your live
- Click Start broadcast, allow camera and microphone access
- 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.spotlightevent 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
Recording and replay
How recording works
Recording happens entirely on the host’s browser side via the MediaRecorder API:
- 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)
- Every 5 seconds (configurable), a WebM chunk is triggered and uploaded via
POST /wp-json/df-nls/v1/shows/{id}/replay/chunk - The chunk is stored as a WordPress attachment, named
dfnls-show-{id}-part-{NNNNN}.webm, withpost_parentpointing to the live - The
wp_dfnls_replay_partstable keeps the order and duration of each chunk
How replay works
On page load in replay mode:
- The viewer calls
GET /wp-json/df-nls/v1/shows/{id}/replaywhich returns the ordered list of segments and the events timeline - Segments are loaded sequentially via the
endedevent of the<video>element (native fallback) - A MediaSource variant enables transparent concatenation if the browser supports it
- 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.
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 accordinglylive: 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
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 settingshost_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_replays— daily. Deletes replays of lives ended more than N days ago (configurable retention). Useswp_delete_attachment(..., true)to also remove the physical file.dfnls_cleanup_stale_signaling— hourly. Purges signaling messages older than 24h and sessions inactive for more than 90 seconds.
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 leavesPOST /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 peerGET /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 IDPOST /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 chunkGET /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 failedorconnection state failederrors - 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_filesizeandpost_max_sizein php.ini (target 20 MB minimum) - Check
LimitRequestBodyon Apache side if applicable - Look at the host console activity log to identify the exact error
- Check the
wp-content/uploadsfolder 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
Secureflag
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(variablevideoBitsPerSecond)
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_dataoption was enabled before uninstallation
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)