Title: Livo Story
Author: livostory
Published: <strong>September 21, 2026</strong>
Last modified: September 22, 2026

---

Search plugins

![](https://ps.w.org/livo-story/assets/banner-772x250.png?rev=3707323)

![](https://ps.w.org/livo-story/assets/icon.svg?rev=3707323)

# Livo Story

 By [livostory](https://profiles.wordpress.org/livostory/)

[Download](https://downloads.wordpress.org/plugin/livo-story.1.8.4.zip)

 * [Details](https://wordpress.org/plugins/livo-story/#description)
 * [Reviews](https://wordpress.org/plugins/livo-story/#reviews)
 *  [Installation](https://wordpress.org/plugins/livo-story/#installation)
 * [Development](https://wordpress.org/plugins/livo-story/#developers)

 [Support](https://wordpress.org/support/plugin/livo-story/)

## Description

Livo Story lets you attach short vertical videos (“stories”) to your WooCommerce
products and display them as a swipeable slider anywhere on your site via shortcode.
Visitors can watch a product story and add the product to their cart directly from
the story card — including variable products, without leaving the story.

**Features**

 * Vertical, swipeable video stories for WooCommerce products, desktop and mobile.
 * Add-to-cart card inside the story, with native WooCommerce variation support.
 * Extensible via the `livostory_extra_cart_fields` filter, so a theme or another
   plugin can add store-specific fields (e.g. a required date) to the add-to-cart
   card without modifying Livo Story itself.
 * Admin dashboard to manage stories per product, reorder them, and track basic 
   view stats.

## Screenshots

[⌊Admin dashboard.⌉⌊Admin dashboard.⌉[

Admin dashboard.

[⌊All Stories: manage every story from one screen.⌉⌊All Stories: manage every story
from one screen.⌉[

All Stories: manage every story from one screen.

[⌊Add Story: upload a video and link it to a product.⌉⌊Add Story: upload a video
and link it to a product.⌉[

Add Story: upload a video and link it to a product.

[⌊Settings: video display and behavior options.⌉⌊Settings: video display and behavior
options.⌉[

Settings: video display and behavior options.

## Installation

 1. Upload the plugin files to `/wp-content/plugins/livo-story`, or install it directly
    through the WordPress plugins screen.
 2. Activate the plugin through the “Plugins” screen in WordPress.
 3. WooCommerce must be installed and active.
 4. Go to the Livo Story admin menu to add a story to a product.
 5. Add the `[livostory-stories]` shortcode to any page or post to display the stories
    slider.

## FAQ

### Does this work with variable products?

Yes. When a story’s product has variations, the add-to-cart card expands to let 
the shopper pick the attributes before adding it to the cart.

### Can I collect extra information before add-to-cart (e.g. a required date)?

Yes, via the `livostory_extra_cart_fields` filter. It receives the current field
list, the `WC_Product`, and the story, and expects an array of field definitions(`
name`, `type`, `label`, `required`, and `options` for a `select` field). Livo Story
ships with no fields registered by default.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“Livo Story” is open source software. The following people have contributed to this
plugin.

Contributors

 *   [ livostory ](https://profiles.wordpress.org/livostory/)

[Translate “Livo Story” into your language.](https://translate.wordpress.org/projects/wp-plugins/livo-story)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/livo-story/), check
out the [SVN repository](https://plugins.svn.wordpress.org/livo-story/), or subscribe
to the [development log](https://plugins.trac.wordpress.org/log/livo-story/) by 
[RSS](https://plugins.trac.wordpress.org/log/livo-story/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.8.4

 * Added the plugin’s icon, banner and screenshots for the WordPress.org listing
   page.

#### 1.8.3

 * Hidden (inactive) stories could still accumulate view records and cart-event 
   attribution through the two public tracking endpoints, even though they are invisible
   everywhere on the storefront; both now check the story’s active status the same
   way the storefront itself does.
 * The per-visitor throttle on both tracking endpoints keyed off an IP address read
   from client-controlled headers (X-Forwarded-For, Client-IP), which a script can
   set to a different value on every request to defeat it entirely. The throttle
   now keys off REMOTE_ADDR, the address the webserver itself sees, which a client
   cannot spoof; the more lenient, header-preferring lookup is kept only for the
   IP stored in analytics, which is a display value, not a security control.
 * Fixed the root cause behind the story modal not opening at all on some pages,
   reported as “no data for container … livostoryStoriesData itself is missing” 
   in the console: the per-instance data was attached via wp_add_inline_script()
   from inside the shortcode itself, which only works if the target script has not
   printed yet — not guaranteed when the shortcode renders from a widget, footer
   area, or page builder that runs after the main content. That data is now collected
   while the shortcode renders and printed on wp_footer, ahead of WordPress’s own
   script-printing, regardless of where on the page the shortcode ran from.
 * Fixed a PHP warning (“Undefined property: stdClass::$thumbnail_url”) logged on
   every story render: the stories table has never had a thumbnail_url column, and
   nothing in the plugin ever writes one, so the five places reading it now treat
   it as always absent instead of triggering a warning.
 * Removed the public “get stories” AJAX endpoint. Nothing in the plugin called 
   it — storefront stories are rendered server-side by the shortcode — so it was
   only an unauthenticated database-query surface.
 * Removed the unused admin “get story” AJAX endpoint for the same reason.
 * Every remaining AJAX handler now checks its nonce with check_ajax_referer() and,
   where the action is privileged, current_user_can(), inline and before reading
   any input, instead of through a shared helper.
 * The story add-to-cart attribution now verifies its nonce before reading any other
   request field.
 * Fixed a database error logged on every activation and version bump: the story
   tables were created with a FOREIGN KEY clause dbDelta() cannot parse, which made
   it emit invalid SQL trying to “fix” the table. The constraint was removed (it
   was never actually created by dbDelta() in the first place) and its cascade-delete
   behavior is now done directly in code when a story is deleted.
 * Fixed the admin “copy shortcode” button throwing “Cannot read properties of undefined(
   reading ‘writeText’)” on any install not served over HTTPS. Two other copies 
   of that function, both missing the non-HTTPS fallback the working one already
   had, were loading after it and silently overwriting it; both were removed and
   the two admin bundles now have an explicit load-order dependency instead of relying
   on registration order.
 * Fixed the front-end story click handler firing twice on a single click, the second
   time with the wrong id, throwing “Cannot read properties of undefined” and restarting
   the video/double-counting the view. The duplicate handler was removed rather 
   than corrected, since only one of the two ever had the right data to begin with.
 * The story modal now logs a diagnostic warning and does nothing instead of throwing
   if its data isn’t available yet at click time (a stale cache, a slow-loading 
   footer script), rather than breaking every other click handler on the page.

#### 1.8.2

 * The nonce added in 1.8.1 to gate story-attributed cart events was necessary but
   not sufficient: WordPress issues the same nonce value to every logged-out visitor,
   and it is printed in plain sight on every page, so a script could still fetch
   it and replay it. A per-visitor, per-story throttle now caps that at one attributed
   event per short window, matching the same protection already in place for view
   tracking.

#### 1.8.1

 * The public “get stories” AJAX endpoint no longer accepts an unbounded `limit`:
   zero, negative, absent or absurdly large values are all clamped to a fixed range
   instead of loading every active story or scanning every product in a category.
 * Add-to-cart events attributed to a story now require a nonce generated for that
   page load. The classic WooCommerce add-to-cart form this rides on carries no 
   nonce of its own, so without this a script could replay a real (story_id, product_id)
   pair to inflate a story’s “added to cart” count without ever visiting the story.

#### 1.8.0

 * New `ids` shortcode attribute: `[livostory-stories ids="7,3,12"]` embeds just
   those stories, in exactly that order. Pages can now show different, hand-picked
   sets, and set their own order without touching the global one.
 * New “Build a shortcode” panel on the All Stories screen. Search a story by title
   or product, click to add it, and the shortcode is written for you with a copy
   button. The search covers every story, not only the twenty rows on the current
   page.
 * Copy buttons now work on installs served over plain HTTP. They relied on `navigator.
   clipboard`, which browsers only expose in a secure context, and failed outright
   everywhere else.
 * The two JavaScript globals the front end relied on (productStoriesConfig, productStoriesData)
   are now prefixed (livostoryConfig, livostoryStoriesData) to avoid colliding with
   another plugin or theme’s global scope.
 * Removed a leftover wp_localize_script() call that wrote to the same global name
   a wp_add_inline_script() call immediately overwrote; it was pure dead weight.
 * The public, logged-out view-tracking endpoint now bounds all self-reported values(
   duration is clamped to a sane range, device type is checked against a fixed list)
   and throttles repeated submissions from the same visitor for the same story, 
   so a script replaying the endpoint’s own public nonce can no longer flood the
   views table with arbitrary rows.

#### 1.7.1

 * The story form is now saved on admin_init, before any output. It used to be handled
   from the page callback, which runs after the admin header is printed, so the 
   redirect could never use wp_safe_redirect() and fell back to an inline script.
 * All remaining inline script and style blocks were moved into enqueued files: 
   the per-instance story payload now attaches to the front-end script handle, and
   the Add Story preview rules live in the admin stylesheet.
 * The shortcode now escapes the “No story found” message it returns.
 * Product prices and variation markup handed to the front-end script are filtered
   through wp_kses_post() before they reach the page, and variation image URLs through
   esc_url(). They are rendered into the DOM by JavaScript, so escaping them server-
   side is the only place it can happen.
 * The story buy button no longer carries a hardcoded Portuguese label; it uses 
   the translated string the plugin already passes to the front end.
 * Dropped a hardcoded /wp-admin/ path from the upload handler; it uses ABSPATH 
   only.
 * Removed load_plugin_textdomain(), which WordPress has not needed for directory-
   hosted plugins since 4.6, and stopped bundling translation files. Translations
   now come from translate.wordpress.org.
 * The “WooCommerce required” notice is limited to this plugin’s own screens and
   the Plugins list, instead of appearing throughout wp-admin.
 * The package now ships the un-minified sources behind dist/, plus the build configuration,
   and the readme documents how to rebuild them.

#### 1.7.0

 * Fixed a fatal error that hit every WooCommerce product page: the social-sharing
   meta tag code called a class that does not exist anywhere in the plugin.
 * WooCommerce is now a declared dependency (“Requires Plugins”), and every entry
   point that touches a WooCommerce API checks for it first, so the plugin can no
   longer fatal on a site where WooCommerce is missing or deactivated.
 * Removed the unused video compression subsystem. It never actually ran — its namespace
   sat outside the plugin’s autoload map, so the class was never loaded — and it
   was the only reason the plugin shipped php-ffmpeg and its dependency tree. The
   packaged plugin drops from ~2.5 MB of bundled vendor code to none.
 * “Requires PHP” now reads 8.2, which is what the plugin already required. It previously
   claimed 7.4, which let sites on older PHP install the plugin and then hit a fatal
   error on every request, wp-admin included.
 * Security and coding-standards pass over the whole plugin: all output is escaped,
   translated strings use the escaping translation functions, every database query
   goes through $wpdb->prepare(), and the admin redesign’s CSS/JS load through wp_enqueue_*
   instead of raw / tags.
 * Video uploads now land straight in uploads/product-stories through the upload_dir
   filter, instead of being written to the default month folder and then moved with
   rename() — a move that could fail silently and leave the upload orphaned.
 * Removed debug logging that wrote form data to the PHP error log on every story
   save.
 * The admin stylesheet no longer pulls the Outfit typeface from Google Fonts at
   runtime. WordPress.org plugins must not load third-party assets, and the stylesheet
   already falls back to the system UI font stack.
 * Removed three unprefixed AJAX actions (delete_story, toggle_story_status, update_story_order).
   They collided with the generic namespace WordPress.org asks plugins to stay out
   of, and they were unreachable anyway — the admin screens use the livostory_-prefixed
   handlers.
 * Added the GPLv3 LICENSE file the plugin header has always pointed at.
 * The shortcode and the front-end AJAX endpoint no longer carry two copies of the
   same query; both now call one method on the stories provider.

#### 1.6.0

 * New Dashboard card: “Most added to cart” — tracks how many times each story’s
   buy button actually added the product to the cart (not just clicks), ranked and
   filterable by the same date range as the rest of the dashboard.
 * Add-to-cart events are only attributed to a story when the click can be verified
   against the product that was actually added, so the count can’t be skewed by 
   an unrelated add-to-cart action elsewhere on the site.

#### 1.5.0

 * Full redesign of the plugin’s admin screens (Dashboard, All Stories, Add Story,
   Settings), matching the new dark/pink-orange visual design.
 * Dashboard: real performance metrics (views, unique viewers, watch time, completion)
   with a period selector and a “most viewed stories” ranking, replacing the previous
   chart-only view.
 * All Stories: search, status filters, drag-to-reorder, and per-story view counts
   in one screen.
 * Fixed a long-standing bug where pagination on the All Stories screen never rendered(
   a variable-name mismatch between the page controller and the template).
 * Fixed the status filter (Active/Hidden) on All Stories, which rendered but never
   actually filtered the list.
 * Added pt_BR translations for all of the above.

#### 1.4.4

 * Fixed “Stories Carousel” and “Rounded Slides” being selectable at the same time—
   they’re the same layout (square vs. rounded corners), so they now share one radio
   group like the rest of the display options.

#### 1.4.3

 * “Rounded Slides” icon now shows three circles with a gradient ring (matching 
   the front-end story ring), like Instagram-style story avatars, instead of a plain
   rounded square.

#### 1.4.2

 * “Rounded Slides” is now a card in the same visual grid as the display layout 
   options, instead of a plain checkbox — it’s a real, available option today, so
   it gets the same styling.

#### 1.4.1

 * Moved the display layout picker into the existing Appearance Settings card, next
   to Rounded Slides, instead of a separate box.
 * “Stories Carousel” (the layout actually in use today) is now the available/default
   option; Grid, Carousel and Stories are the “Coming soon” ones.

#### 1.4.0

 * Added a display layout picker to Settings (Grid, Carousel, Stories, Stories Carousel
   cards). Only Grid is functional today; the others are marked “Coming soon” — 
   no artificial pro/paid gating.

#### 1.3.5

 * Fixed the activation date field rendering as an oversized, apparently empty box
   on iOS Safari (the native date control there sizes itself from the inherited 
   line-height, unlike desktop).

#### 1.3.4

 * Translated the remaining Portuguese source strings in the admin “Add Story” and“
   All Stories” screens that were missed in 1.2.0 (unaccented words weren’t caught
   by the earlier sweep).

#### 1.3.3

 * Fixed Tailwind utilities not applying on elements that carry the `.wrap` class
   themselves (e.g. centering on the “Add Story” screen) — the previous ancestor-
   based scoping never matched same-element cases.

#### 1.3.2

 * Fixed the release/packaging scripts still using a leftover boilerplate slug (`
   coffee-wc-checkout`) instead of `livo-story`, which affected the built asset 
   public path and the release zip’s folder/file name.
 * The release build now bundles `readme.txt` and the real `composer.json` (previously
   a generic placeholder without the actual dependencies).
 * `yarn release` now runs `composer install --no-dev` itself, so it alone produces
   a submission-ready package.

#### 1.3.1

 * Guarded against a fatal error on hosts where the optional php-ffmpeg library 
   isn’t installed (video compression is now skipped gracefully in that case, same
   as when the ffmpeg binary itself is missing).

#### 1.3.0

 * Tailwind CSS is now compiled and bundled locally instead of loaded from cdn.tailwindcss.
   com, per WordPress.org guidelines against remote-loaded code.
 * Fixed an admin asset-loading regression (an internal page-slug check was accidentally
   changed during the 1.2.0 i18n pass).

#### 1.2.0

 * All source strings (PHP and JS) are now in English by default, per WordPress.
   org guidelines.
 * Added a Portuguese (Brazil) translation (`languages/livo-story-pt_BR.mo`) so 
   existing installs keep the same UI language.

#### 1.1.6

 * Removed hardcoded references to a specific store’s assets from the bundled checkout
   styles.
 * Unified the plugin’s text domain to `livo-story` throughout.
 * Added a `readme.txt`.

#### 1.1.5

 * Added the `livostory_extra_cart_fields` filter so store-specific add-to-cart 
   fields don’t need to be hardcoded in the plugin.
 * Fixed variable product add-to-cart matching for custom (non-taxonomy) attributes.
 * In-place add-to-cart card expansion, replacing the previous popup.
 * Removed the external Swiper CSS CDN request in favor of the already-bundled local
   copy.

## Meta

 *  Version **1.8.4**
 *  Last updated **1 day ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.0 or higher **
 *  Tested up to **7.1.2**
 *  PHP version ** 8.2 or higher **
 * Tags
 * [Social commerce](https://wordpress.org/plugins/tags/social-commerce/)[stories](https://wordpress.org/plugins/tags/stories/)
   [video](https://wordpress.org/plugins/tags/video/)[woocommerce](https://wordpress.org/plugins/tags/woocommerce/)
 *  [Advanced View](https://wordpress.org/plugins/livo-story/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/livo-story/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/livo-story/reviews/)

## Contributors

 *   [ livostory ](https://profiles.wordpress.org/livostory/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/livo-story/)