{"id":344031,"date":"2026-08-06T15:46:48","date_gmt":"2026-08-06T15:46:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/oncue\/"},"modified":"2026-08-06T15:46:12","modified_gmt":"2026-08-06T15:46:12","slug":"oncue-liveblogging","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/oncue-liveblogging\/","author":23536589,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.7","stable_tag":"1.0.7","tested":"7.0.3","requires":"6.5","requires_php":"8.0","requires_plugins":null,"header_name":"OnCue Liveblogging","header_author":"thelettertwo","header_description":"Team liveblogging for WordPress: a real-time liveblog posted from wp-admin, with opt-in field-posting from Slack and Telegram, More Coverage, share cards, and moderation.","assets_banners_color":"f6f3ec","last_updated":"2026-08-06 15:46:12","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/oncue.thelettertwo.com","header_author_uri":"https:\/\/thelettertwo.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":57,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.7":{"tag":"1.0.7","author":"oncue","date":"2026-08-06 15:46:12"}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3636813,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3636813,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3636813,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3636813,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":{"oncue\/liveblog":{"name":"oncue\/liveblog","title":"OnCue Liveblog"}},"tagged_versions":["1.0.7"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3636813,"resolution":"1","location":"assets","locale":"","width":1600,"height":1509},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3636813,"resolution":"2","location":"assets","locale":"","width":1600,"height":2967}},"screenshots":{"1":"The live console: post, edit, and pin updates while the event runs.","2":"The reader view, inheriting the host theme's typography.","3":"Connections: enable only the integrations you want.","4":"Event stats."}},"plugin_section":[],"plugin_tags":[34890,576,575,3565,9171],"plugin_category":[],"plugin_contributors":[274654,274655],"plugin_business_model":[],"class_list":["post-344031","plugin","type-plugin","status-publish","hentry","plugin_tags-breaking-news","plugin_tags-live-blogging","plugin_tags-liveblog","plugin_tags-slack","plugin_tags-telegram","plugin_contributors-oncue","plugin_contributors-thekenyeung","plugin_committers-oncue"],"banners":{"banner":"https:\/\/ps.w.org\/oncue-liveblogging\/assets\/banner-772x250.png?rev=3636813","banner_2x":"https:\/\/ps.w.org\/oncue-liveblogging\/assets\/banner-1544x500.png?rev=3636813","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/oncue-liveblogging\/assets\/icon-128x128.png?rev=3636813","icon_2x":"https:\/\/ps.w.org\/oncue-liveblogging\/assets\/icon-256x256.png?rev=3636813","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/oncue-liveblogging\/assets\/screenshot-1.png?rev=3636813","caption":"The live console: post, edit, and pin updates while the event runs."},{"src":"https:\/\/ps.w.org\/oncue-liveblogging\/assets\/screenshot-2.png?rev=3636813","caption":"The reader view, inheriting the host theme's typography."}],"raw_content":"<!--section=description-->\n<p>OnCue's core is a real-time liveblog posted from the WordPress admin: create an\nevent, drop the OnCue block into a post, and post updates from the live console.\nEverything beyond the core is an opt-in module, off by default:<\/p>\n\n<ul>\n<li>Slack ingestion \u2014 a dedicated channel becomes the liveblog feed.<\/li>\n<li>Telegram ingestion \u2014 a bot in a group (or DM) posts every message.<\/li>\n<li>More Coverage \u2014 a linked-headline list of the publication's own articles for the event.<\/li>\n<li>Reader share cards \u2014 per-entry share row posting rich Open Graph cards.<\/li>\n<li>Moderation gate \u2014 approval-before-publish per blog or per source.<\/li>\n<\/ul>\n\n<p>A disabled module registers no REST routes and schedules no jobs; the attack\nsurface is exactly the set of enabled features.<\/p>\n\n<h3>Security note on stored secrets<\/h3>\n\n<p>OnCue encrypts stored channel credentials (Slack\/Telegram tokens and secrets)\nat rest with libsodium, on by default. The encryption key never lives in the\ndatabase, so a database dump alone cannot decrypt them. Key source:<\/p>\n\n<ul>\n<li><code>ONCUE_ENCRYPTION_KEY<\/code> in <code>wp-config.php<\/code> (a 32+ char random string) if you\nset one \u2014 preferred, because you can rotate it independently of WordPress; or<\/li>\n<li>your existing WordPress security keys (AUTH_KEY etc.), which are already in\n  wp-config.php \u2014 so encryption works with no extra setup on any properly\ninstalled site.<\/li>\n<\/ul>\n\n<p>Only a site with neither (no real salts and no dedicated key) falls back to\nplaintext, and the Connections screen flags that loudly.<\/p>\n\n<p>What is <em>not<\/em> encrypted, by design: liveblog entries and other public content\n(they are served to readers; encrypting them would break the live stream), and\nnon-secret identifiers like the house-account user ID or the public Slack\nclient ID. Encrypting the whole database or disk is the host's responsibility\n(encrypted volumes \/ MySQL TDE), not a plugin's.<\/p>\n\n<p>Changing the key source (e.g. rotating WordPress salts without setting a\ndedicated key) makes previously stored credentials undecryptable \u2014 re-enter\nthem under Connections if that happens.<\/p>\n\n<h3>Typography<\/h3>\n\n<p>The reader inherits the host theme's fonts throughout, including buttons and\nform controls. The generated share-card image uses the site's own typeface\ntoo: OnCue resolves the theme's body font (theme.json \/ Font Library) to a\nlocal TTF\/OTF file for GD. If the theme ships fonts only as woff2 (which GD\ncannot read), upload a TTF of the same family to the Font Library, or point\nthe <code>oncue_card_font<\/code> filter at a font file; otherwise the card falls back to\nGD's built-in font.<\/p>\n\n<h3>External services<\/h3>\n\n<p>OnCue does not phone home and ships with every integration off. It contacts a\nthird-party service only when you enable that integration and provide your own\naccount or API key, and only to deliver the feature you turned on. Nothing is\nsent to OnCue's authors. The services, what triggers a request, and what data\nleaves your site:<\/p>\n\n<ul>\n<li>Slack (ingestion \/ relay) \u2014 only if you connect Slack. Sends liveblog entries\nyou relay out, and receives messages from a channel you designate. Terms:\nhttps:\/\/slack.com\/legal \u2014 Privacy:\nhttps:\/\/slack.com\/trust\/privacy\/privacy-policy<\/li>\n<li>Telegram (ingestion \/ relay \/ contributor sign-in) \u2014 only if you connect a\nTelegram bot. Sends relayed entries and receives messages from the bot's chat.\nSeparately, once a bot is connected, OnCue loads Telegram's official login\nwidget script (https:\/\/telegram.org\/js\/telegram-widget.js) inside wp-admin so\ncontributors can link their Telegram account in one click; Telegram receives\nthe request for that script and the sign-in it performs. That script is never\nloaded on the public side of your site, and never loaded at all until you\nconnect a bot. Contributors who prefer not to use it can link by opening the\nbot in the Telegram app instead. Terms: https:\/\/telegram.org\/tos \u2014 Privacy:\nhttps:\/\/telegram.org\/privacy<\/li>\n<li>Twilio (SMS relay) \u2014 only if you connect Twilio. Sends entry text to the\nnumbers you configure. Terms: https:\/\/www.twilio.com\/en-us\/legal\/tos \u2014\nPrivacy: https:\/\/www.twilio.com\/en-us\/legal\/privacy<\/li>\n<li>Microsoft Teams \/ Google Chat \/ Signal (relay) \u2014 only if you connect them.\nSends relayed entry text to the webhook\/space you configure. Microsoft:\nhttps:\/\/www.microsoft.com\/servicesagreement \u2014 Google:\nhttps:\/\/policies.google.com\/terms \u2014 Signal: https:\/\/signal.org\/legal\/<\/li>\n<li>Bluesky \/ ATProto (curation \/ relay) \u2014 only if you connect a Bluesky account.\nSearches public posts and, if enabled, mirrors marked entries out. Terms:\nhttps:\/\/bsky.social\/about\/support\/tos \u2014 Privacy:\nhttps:\/\/bsky.social\/about\/support\/privacy-policy<\/li>\n<li>Threads \/ Meta (relay) \u2014 only if you connect a Threads account by pasting a\nlong-lived access token. Publishes the entries you mark into one thread on\nthat account (via graph.threads.net) and periodically refreshes the token.\nNothing is sent unless you enable Threads for an event and mark a post. Terms:\nhttps:\/\/www.facebook.com\/legal\/terms \u2014 Privacy:\nhttps:\/\/privacycenter.instagram.com\/policy<\/li>\n<li>YouTube Data API (coverage) \u2014 only if you add a YouTube API key. Sends search\nqueries for the event's coverage. Terms: https:\/\/www.youtube.com\/t\/terms \u2014\nGoogle Privacy: https:\/\/policies.google.com\/privacy<\/li>\n<li>Google Analytics (Stats) \u2014 only if you enable the analytics bridge and\/or add\na GA4 service-account key. Reader interactions flow through the Google tag\nalready on your pages (your tag's consent tooling governs them); Stats reads\naggregate figures back from your own GA4 property. Terms:\nhttps:\/\/marketingplatform.google.com\/about\/analytics\/terms\/us\/ \u2014 Privacy:\nhttps:\/\/policies.google.com\/privacy<\/li>\n<li>AI providers for the \"Key highlights\" summary (Crawler) \u2014 only if you choose a\nprovider and add your own key. The chosen event's own updates and coverage are\nsent to generate the summary. Anthropic:\nhttps:\/\/www.anthropic.com\/legal\/consumer-terms \/\nhttps:\/\/www.anthropic.com\/legal\/privacy \u2014 OpenAI:\nhttps:\/\/openai.com\/policies\/terms-of-use \/\nhttps:\/\/openai.com\/policies\/privacy-policy \u2014 Google Gemini:\nhttps:\/\/ai.google.dev\/gemini-api\/terms \/\nhttps:\/\/policies.google.com\/privacy \u2014 Self-hosted \/ OpenAI-compatible: governed\nby the endpoint you point it at.<\/li>\n<\/ul>\n\n<h3>Development<\/h3>\n\n<p>The complete, unminified sources for the block editor and console bundles ship\nin <code>src\/<\/code> inside this plugin, alongside the <code>webpack.config.js<\/code> used to build\nthem.<\/p>\n\n<ul>\n<li><code>npm install &amp;&amp; npm run build<\/code> builds the block editor and console bundles.<\/li>\n<li><code>npm run env:start<\/code> boots a local WordPress with the plugin active (requires Docker).<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate OnCue. A top-level <strong>OnCue<\/strong> menu appears in wp-admin.<\/li>\n<li>Go to <strong>OnCue \u2192 New liveblog<\/strong> and create an event.<\/li>\n<li>Edit the post or page that should carry the liveblog and insert the\n<strong>OnCue Liveblog<\/strong> block, choosing your event. The <code>[oncue]<\/code> shortcode works\nin classic editors and page builders.<\/li>\n<li>Post updates from <strong>OnCue \u2192 Live console<\/strong>.<\/li>\n<\/ol>\n\n<p>Everything beyond that is optional. To let reporters post from Slack or\nTelegram, go to <strong>OnCue \u2192 Connections<\/strong>, enable the module, and follow the\nsetup steps for that platform. No integration is enabled by default, and none\nis required to run a liveblog.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20a%20slack%20or%20telegram%20account%20to%20use%20oncue%3F\"><h3>Do I need a Slack or Telegram account to use OnCue?<\/h3><\/dt>\n<dd><p>No. The core liveblog runs entirely inside WordPress. Slack and Telegram are\nopt-in modules for teams who want reporters posting from the field.<\/p><\/dd>\n<dt id=\"does%20oncue%20require%20an%20account%20or%20send%20anything%20to%20its%20authors%3F\"><h3>Does OnCue require an account or send anything to its authors?<\/h3><\/dt>\n<dd><p>No. There is no account, no licence key, and no telemetry. OnCue contacts a\nthird-party service only when you connect that service yourself. See the\nExternal services section below for the full list.<\/p><\/dd>\n<dt id=\"does%20the%20ai%20summary%20feature%20need%20an%20api%20key%3F\"><h3>Does the AI summary feature need an API key?<\/h3><\/dt>\n<dd><p>Yes, your own. The \"Key highlights\" module is bring-your-own-key and supports\nAnthropic Claude, OpenAI, Google Gemini, and any OpenAI-compatible endpoint\nincluding self-hosted ones. It is off until you choose a provider and add a\nkey. Summaries are grounded in the event's own updates and coverage, and every\nbullet carries a citation.<\/p><\/dd>\n<dt id=\"where%20are%20my%20api%20tokens%20stored%3F\"><h3>Where are my API tokens stored?<\/h3><\/dt>\n<dd><p>Encrypted at rest with libsodium, using a key held outside the database. See\nthe security note below for details and for how to set a dedicated key.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20my%20liveblogs%20if%20i%20delete%20the%20plugin%3F\"><h3>What happens to my liveblogs if I delete the plugin?<\/h3><\/dt>\n<dd><p>Deleting OnCue erases them. Every liveblog update, poll, contributor link and\nconnection setting lives in OnCue's own database tables, and deleting a plugin\nin WordPress drops those tables. This is not reversible without a database\nbackup.<\/p>\n\n<p>Your liveblog posts and uploaded images are deliberately kept \u2014 they are your\ncontent and the public record \u2014 but with the updates gone they will be empty.<\/p>\n\n<p>Deactivating OnCue changes nothing: it stops the plugin running and leaves all\ndata in place. Only Delete removes it. If you are troubleshooting, or moving\nthe plugin between folders, deactivate rather than delete.<\/p><\/dd>\n<dt id=\"can%20readers%20post%20or%20comment%3F\"><h3>Can readers post or comment?<\/h3><\/dt>\n<dd><p>Not directly. Readers can react and vote in polls if you enable those modules.\nEntries come only from your team, through wp-admin or a connected chat channel.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.7<\/h4>\n\n<ul>\n<li>Security hardening throughout, in response to the WordPress.org review.\nRequest data is sanitized at the point it is read, and every dynamic value is\nescaped on the line that prints it.<\/li>\n<li>Telegram sign-in payloads are reduced to the fields Telegram actually sends,\neach cleaned for its own field type, and the verified account ID must be a\npositive integer before it is stored. A payload that fails either check is\nrejected rather than trusted.<\/li>\n<li>Analytics no longer reads a server value without sanitizing it first, and the\nclient IP is validated as a real IP address before it is hashed. It is still\nnever stored.<\/li>\n<li>Event setup sanitizes the authors, tags, colors, module toggles, and\nper-module settings it receives, instead of relying on a later pass.<\/li>\n<li>Credentials for Slack, Telegram, Google Analytics, and the AI providers are\nsanitized as they are read from the settings forms.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First stable release, and OnCue's first release on WordPress.org.<\/li>\n<li>Core liveblog: events, the OnCue Liveblog block and <code>[oncue]<\/code> shortcode, and\nthe live console for posting, editing, pinning, and moderating updates.<\/li>\n<li>Opt-in field posting from Slack and Telegram, with a moderation gate that can\nbe applied per event or per source.<\/li>\n<li>Opt-in modules: More Coverage, reader share cards, reader reactions, polls,\nper-event appearance, link preview cards, and outbound relay to Slack,\nTelegram, Bluesky, Twilio SMS, Microsoft Teams, Google Chat, and Signal.<\/li>\n<li>Built-in cookieless per-event analytics that require no third-party account.<\/li>\n<li>Bring-your-own-key \"Key highlights\" summaries with grounded, cited output,\nsupporting Anthropic Claude, OpenAI, Google Gemini, and OpenAI-compatible or\nself-hosted endpoints.<\/li>\n<li>Channel credentials encrypted at rest with libsodium, using a key held\noutside the database.<\/li>\n<li>Fully translatable, with a bundled POT file.<\/li>\n<\/ul>\n\n<p>Releases below predate the WordPress.org listing and were distributed directly.<\/p>\n\n<h4>0.1.34<\/h4>\n\n<ul>\n<li>Reader reactions: an opt-in, per-event thumbs-up on individual updates, with\nno sign-in required and counts that refresh live.<\/li>\n<li>Bluesky threads can now carry a per-event official hashtag, set in Event Setup.<\/li>\n<\/ul>\n\n<h4>0.1.33<\/h4>\n\n<ul>\n<li>New Appearance tab: per-event accent, card background, border, and muted-text\ncolors with a readability check, plus contained or full-width layout.<\/li>\n<li>Links pasted in the console, or shared from Slack or Telegram, now render as\npreview cards with headline, description, image, and source.<\/li>\n<li>Expanded Bluesky support.<\/li>\n<\/ul>\n\n<h4>0.1.25<\/h4>\n\n<ul>\n<li>Built-in per-event analytics that need no Google account: reader numbers,\nunique readers, shares, interactions, sources, devices, countries, and a live\n\"reading right now\" count.<\/li>\n<li>Collection is cookieless and stores no personal data. Visitor counts use a\ndaily-rotating fingerprint; IP addresses derive an approximate country and are\nnever stored. All data stays in your own database.<\/li>\n<\/ul>\n\n<h4>0.1.24<\/h4>\n\n<ul>\n<li>First public release.<\/li>\n<\/ul>","raw_excerpt":"Team liveblogging for WordPress, built for the reporter in the field with a phone.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/344031","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=344031"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/oncue"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=344031"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=344031"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=344031"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=344031"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=344031"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=344031"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}