Event Tickets with Ticket Scanner

Mô tả

Run your entire ticketing workflow inside WordPress. No platform service fees, no per-ticket commissions — you only pay your payment processor (Stripe, PayPal, etc.) like any WooCommerce product.

Event Tickets with Ticket Scanner turns any WooCommerce product into a scannable event ticket — complete with QR code, downloadable PDF, and a built-in mobile ticket scanner for your team at the door.

Unlike ticketing platforms that charge service fees on paid tickets, this plugin adds no per-ticket commission — you keep your ticket revenue (minus your payment processor’s standard fee). Unlike other WordPress plugins, you get a visual seating plan designer and a ticket PDF designer included — not as expensive add-ons.

Active on 1,000+ WordPress sites — from small community events to large concert venues.

Who is this for?

  • Concert & festival organizers — sell general admission or assigned seats with interactive seat selection
  • Theaters & venues — design your seating layout with drag & drop, let customers pick their seats
  • Sports events & arenas — handle high volumes with offline fallback and team scanner access
  • Conferences & congresses — give attendees a private companion portal with programme, speakers, downloads and time-controlled access, opened straight from the ticket (see “Congress & Attendee Portal” below)
  • Single events with an info app — any event, not just big congresses: build a mobile info page (schedule, speaker info, downloads, support pages) your visitors open with their ticket — no separate app to install
  • Clubs, spas, gyms & theme parks — sell multi-entry passes, family tickets, or memberships with expiration
  • Community events & fundraisers — get started in minutes with the free version (up to 50 tickets)

How it works — 3 steps

  1. Install the plugin and create a ticket list under “Event Tickets”
  2. Enable “Ticket Sales” on any WooCommerce product
  3. Customers receive a unique QR code ticket — scan and redeem at the entrance

That’s it. No coding required. Watch the quickstart video

🎨 Visual Seating Plan Designer

Create professional venue layouts without any design tools:

  • Drag & drop seats, shapes, labels, and text onto your canvas
  • Upload venue floor plans as background images
  • Rotate, duplicate, and bulk-edit elements
  • Color-code seat categories and pricing tiers
  • Customers see a real-time interactive seat map during checkout
  • Seats are automatically blocked during checkout and released on cancel/refund

🎟️ Ticket PDF Designer

Design tickets that match your brand — not generic templates:

  • Add your logo, custom colors, header and background images
  • Position QR codes exactly where you want them
  • Create event badges for staff and VIP passes
  • Multi-page PDF support with attached documents
  • Full bleed mode for edge-to-edge designs

📱 Built-in Ticket Scanner

No extra app needed. The scanner runs in any mobile browser — or install it as a PWA:

  • Scan QR codes with your phone camera — works on iOS and Android
  • Install as PWA — add to home screen for instant launch without browser chrome
  • Fullscreen mode — immersive scanning with a single tap
  • Haptic feedback — vibration confirms valid/invalid tickets instantly
  • Grant team members scanner access via Auth Tokens (no WordPress login needed)
  • See ticket details, seat position, and venue map instantly after scan
  • Voice output confirms valid/invalid tickets for fast processing
  • Protection against fake tickets, double redemption, and brute-force attempts
  • Supports hardware barcode scanners for high-traffic entrances
  • Customizable theme color to match your brand

📲 Vollstart Wallet — All Tickets in One App

Your customers can collect tickets from multiple shops in one free app:

  • Vollstart Wallet at wallet.vollstart.com — a Progressive Web App that works on iOS, Android, and desktop
  • Tickets are added with one click from the ticket page or order email
  • QR code always available — even offline
  • Privacy first — ticket data flows directly from your shop to the customer’s browser. Vollstart never receives or stores any data
  • Learn more about security & privacy

Enable it in Settings Digital Wallets. Free for all users.

🎓 Congress & Attendee Portal

Give ticket holders a private event portal — no extra login, no separate app. Assign a congress to any ticket product and buyers reach it straight from their ticket ID.

  • Organize content into pages — a start page plus as many pages as you need (Speakers, Programme, Downloads, Sponsors …), with a sidebar on desktop and a hamburger menu on mobile
  • Rich section types — formatted text, a day-by-day programme schedule, downloadable files, link lists, image galleries, single images, and embedded videos (paste a YouTube/Vimeo link or upload your own)
  • Password-protect individual sections for VIP or speaker-only content
  • Fast by design — the start page loads instantly and other pages are fetched on demand, so even congresses with dozens of speakers stay snappy
  • Installable & offline-friendly — the portal ships as a mini Progressive Web App
  • Time-controlled access — open the portal a set number of hours before the event and keep it available for a chosen number of days afterwards
  • Recurring events — duplicate a congress as a “new edition” in one click

Build it under the Congresses menu, assign it in the product’s Event Tickets tab, and optionally add a portal link to the order email. Included free.

Powerful Ticket Types

  • Single entry — classic one-time event ticket
  • Multi-entry passes — allow multiple scans (configurable limit)
  • Family tickets — generate multiple tickets per order item
  • Memberships & season passes — set expiration dates
  • Day chooser tickets — let customers pick their event date at checkout
  • Purchase allowance codes — require a valid ticket or access code before a product can be bought. Use it for presale and access codes, or to require a ticket from an earlier event (for example a group-stage ticket in order to buy the final). Per product you decide whether a code unlocks one purchase or several

Built for WooCommerce

  • Works with product variants (e.g., VIP vs. General Admission)
  • Tickets auto-generate on order completion
  • Refunded orders automatically recover and recycle ticket numbers
  • Compatible with WooCommerce Subscriptions
  • Works with WooCommerce PDF Invoices & Packing Slips
  • WPML compatible for multilingual stores

Free vs. Premium

The free version covers everything you need to start selling tickets — ideal for small events up to 50 tickets:

  • ✅ Ticket generation with QR codes (up to 50 tickets, 5 ticket lists)
  • ✅ PDF ticket download (via link in email)
  • ✅ Built-in ticket scanner
  • ✅ Interactive seating plan designer (1 plan, up to 20 seats)
  • ✅ Seat selection at checkout
  • ✅ Multi-entry and family tickets
  • ✅ Day chooser for date-based events
  • ✅ Congress / attendee portal (pages, programme, downloads, media, password-protected sections)
  • ✅ Purchase allowance codes (presale/access codes, or require a ticket from an earlier event)
  • ✅ Webhooks for third-party integrations

Premium adds professional features for larger events and removes all ticket limits:

  • 🔓 PDF ticket as email attachment (not just a link)
  • 🔓 Team scanner access via Auth Tokens
  • 🔓 Calendar invites (ICS files) in emails
  • 🔓 Custom flyers and multi-page PDFs
  • 🔓 CVV security check on tickets
  • 🔓 Brute-force IP blocking
  • 🔓 Unlimited tickets (removes the 50-ticket free limit)
  • 🔓 Advanced shortcodes for ticket display and validation

Get Premium

Links

Ảnh màn hình

Cài đặt

Requirements

  • WordPress 5.0 or greater
  • WooCommerce 6.0 or greater
  • PHP 8.1 or greater (PHP 8.4 compatible)
  • PHP extensions: php-curl, php-imagick

Installation

  1. Go to Plugins Add New in your WordPress admin
  2. Search for “Event Tickets with Ticket Scanner”
  3. Click Install Now, then Activate
  4. Go to Event Tickets in your admin menu and create your first ticket list
  5. Edit any WooCommerce product open the Event Tickets tab enable ticket sales

Quick Setup

The plugin extends WooCommerce so any product can become a ticket. Enable the checkbox on your product, assign a ticket list, and you’re ready to sell.

Tip: Set the product as “Virtual” so WooCommerce auto-completes the order and triggers ticket generation immediately after payment.

To test: Create a manual order in WooCommerce, set it to “Completed”, and check the order email for the ticket link.

For a step-by-step walkthrough, watch the quickstart video.

Hỏi đáp

Do I need any other plugins?

You need WooCommerce (free) to handle payments and orders. Everything else is included — no additional ticketing add-ons required.

Does this work without WooCommerce?

WooCommerce is required for selling tickets. However, you can use the plugin to manage and validate ticket lists manually without WooCommerce sales.

Can my team scan tickets without a WordPress account?

Yes! Premium includes Auth Tokens that give your door staff scanner access via a simple URL — no login required.

Does the scanner work offline?

The scanner is browser-based and requires an internet connection. For large events, the plugin includes offline fallback options to prevent interruptions.

Can customers choose their own seats?

Yes. Design your venue layout with the drag & drop seating designer, and customers will see an interactive seat map during checkout where they can pick available seats.

What ticket types can I create?

Single entry, multi-entry passes, family tickets (multiple tickets per purchase), memberships with expiration dates, and day-chooser tickets where customers pick their event date.

How are tickets delivered to customers?

In the free version, the order confirmation email includes a link to download the ticket PDF and view the QR code. Premium allows attaching the PDF directly to the email and adding calendar invites (ICS).

What happens when an order is refunded?

The ticket is automatically deactivated, the assigned seat is released, and the ticket number is recovered for reuse.

Is the plugin compatible with WPML?

Yes. WPML is supported for multilingual ticket sales. The plugin also ships translations for German, Spanish, French, Italian, Hungarian, Japanese, Dutch, Portuguese, and Chinese.

What if I exceed the free ticket limit?

The free version supports up to 50 tickets. If you reach the limit, the plugin shows a notice in the admin area (your customers are never blocked from purchasing). Premium removes the limit entirely.

Can I use my own QR code or barcode scanner hardware?

Yes. The built-in scanner page accepts input from hardware barcode scanners in addition to camera-based QR scanning.

How do I prevent ticket fraud?

Every ticket number is unique. The scanner detects duplicate redemption attempts. Premium adds CVV verification and brute-force IP blocking for additional security.

What is the congress / attendee portal?

It’s a private event portal you can attach to a ticket product — organized into pages (start page, speakers, programme, downloads, sponsors, etc.) with text, schedules, files, image galleries and embedded videos. Ticket holders open it directly via their ticket, no separate account needed. You can password-protect individual sections, control when the portal opens and how long it stays available, and the page works offline as a mini PWA. It’s included in the free version; build it under the Congresses menu and assign it in the product’s Event Tickets tab.

Đánh giá

9 Tháng 9, 2026
Overall I like this Plugin a lot. It is relatively easy to setup and the built-in Scanner works without problems. Customer Support is also very courteous and fast. The only "downside" I see from my Standpoint as a WordPress Beginner is the level of customisation this Plugin offers. WooCommerce is already tricky with lots of Options, and there are even more options in this Plugin. I wish there was some kind of a "simple Mode" that would break it all down to the bare minimum and get rid of the technical fluff. Regardless of that, I can absolutely recommend this Plugin for all event Organizers who are looking for an easy to implement and solid solution.
15 Tháng 2, 2026 1 trả lời
Threw error right after installing, that prevented me from accessing admin panel. Had to remove it manually, to get site back to working order. (System conforms with published requirements.)Also unnecessary bloated. Bigger that Woocommerce, although doing way less.
21 Tháng 1, 2026
The support guys were quick and helpful. Strongly recommend the plugin.
7 Tháng 12, 2024
It seems like a great plugin and extremely easy to use. I've checked out several other options, but this one was the most straight – forward. I also received pre-sell support, very fast and accurate, exchanged some emails to clarify the possibilities and limitations. The only one is that it doesn't wok offline and I will love it if this can be upgraded in the future.Great job!
Đọc tất cả 24 đánh giá

Người đóng góp & Lập trình viên

“Event Tickets with Ticket Scanner” là mã nguồn mở. Những người sau đã đóng góp vào plugin này.

Những người đóng góp

Nhật ký thay đổi

3.2.4 – 2026-09-29

  • New: Deleting a ticket list that still contains tickets is now blocked by default. The list delete dialog has a new checkbox “Block if list still contains tickets” (checked by default) — unchecking it allows the delete anyway. Prevents accidentally orphaning tickets whose QR code, PDF and scanner checks depend on the list. (#015122)
  • New: You decide how long the ticket scanner ignores a repeated scan of the same ticket — set the waiting time in seconds in the global options (default 7 seconds), so the camera never picks up the same ticket twice by accident.

3.2.3 – 2026-09-27

  • New: The seat map opens as a fullscreen overlay on every device. The confirm buttons sit in a footer that stays visible at the bottom edge, so they can no longer be cut off on small phone displays. Close anytime with the large X in the top right corner. (#015084)
  • New: Zoom buttons beside the seat map. Stacked vertically in a narrow bar on the right, they never cover the map. Zooming is useful on phones to pick the right seat on large plans.
  • New: Global option “Confirm seat selection automatically once complete” (default off) — the seat map confirms as soon as the customer has picked all seats, one less tap on mobile.

3.2.2 – 2026-09-22

  • Fix: Redeem operations are now protected against parallel scanner writes (optimistic locking). When two devices redeem or edit the same ticket code at the same moment, the second write is detected, re-read and safely retried instead of silently overwriting the first one’s redeem entry. (#014976)
  • New: Admin notice on the product edit screen when the product’s seating plan has seats but was never published — until now the product page simply showed no seat selection, with no hint why. The notice links straight to the plan for publishing. (#015050)
  • Fix: On MariaDB servers without strict mode, a never-published seating plan could be treated as published (“0000-00-00” zero-date) — the product page then rendered an empty plan instead of none. Zero dates are now handled correctly. (#015050)
  • Fix: Publishing a seating plan did not sync the seats table — after deleting and re-creating seats in the designer, the shop showed only a fraction of the seats (or none) while the designer showed them all. Publish now re-activates the plan’s seats so the shop matches the designer. (#015050)
  • Fix: The seat statistics (“total seats / available”) counted inactive and deleted seats, reporting seats as available that the shop could not sell. Counts now match what the seat selector actually offers. (#015050)
  • Fix: Seating-plan JSON exports are timestamped down to the second in the download filename so multiple exports on the same day do not overwrite each other.
  • Fix: The seat-map selector endpoint could still show deleted decorations (rect9) because getPlanForProductFrontend merged with array_replace_recursive directly instead of using the helper that replaces element lists. The selector now renders exactly the published decorations. (#015050)
  • Fix: The shop’s seat map could show deleted decorations and seats from an old layout version (e.g. overlapping “ghost” seats) although the designer showed the current plan — the page merged the plan’s legacy meta column into the current published version, and list-merging resurrects deleted elements. The seat map now renders exactly the published version. (#015050)
  • Fix: Seat maps stayed empty on MySQL 8 servers with strict SQL mode — comparing the (empty) event date against a DATE column aborted the seat query with “Incorrect DATE value” while the shop showed no error. Empty and zero dates are now normalized before every seat query. The support info block additionally shows the server’s SQL mode. (#015050)
  • New: “Import Plan (JSON)” next to “Add Seating Plan” — restores a plan export in one click. Two clearly explained modes: create a new plan (gets “(imported)” added, stays unpublished for review) or replace the draft of an existing plan (published version stays live until you publish; sold tickets are never touched). Seat dates are now stored and compared as integer timestamps with self-healing backfill of existing rows — MySQL 8 strict mode can no longer break seat maps. (#015050)
  • New: The seating plan designer and the seat list show an approximate element limit (“n / ~2000”) — plans are stored as JSON and saving extremely large plans can fail silently depending on the server configuration. The counter turns red with a warning when the approximate maximum is reached. (#015050)
  • New: Seating plan designer: “Navigator” — a collapsible element list between the properties panel and the save buttons. Every seat, decoration, line and label is listed by name; click a row to select the element (works for overlapping elements that are hard to click on the canvas), hover to highlight it on the canvas. Essential for debugging customer plans. (#015050)
  • Fix: Deleted elements in the seating plan designer came back after saving and reopening the plan — the server merged the new element list into the stored one instead of replacing it, resurrecting every deleted decoration, line and label. This made plans impossible to clean up (the root cause behind seats never matching the designer). Lists are now replaced on save. (#015050)
  • Fix: Publishing a seating plan raced the draft upload — the publish request fired on a fixed timer instead of waiting for the save to finish, so on slower connections the shop was published with a stale draft while the editor showed “published successfully”. Publish now waits for the save roundtrip and aborts with a clear error if saving fails. (#015050)
  • New: “Export Plan (JSON)” button in the seating plan seat view — downloads the complete plan (canvas, decorations, draft, published version and all seats) without any customer data, so a plan can be shared with support and re-created 1:1 for debugging. (#015050)
  • Tweak: The “Starter plugin is installed” warning now recognizes when the full Premium plugin is already installed next to the Starter and tells you to simply delete the Starter, instead of suggesting a Premium upload you do not need. (#015050)

3.2.1 – 2026-09-18

  • Fix: With “Reserve seat only when adding to cart” enabled, the reservation was stored under wrong identifiers — the seat was not reliably blocked for other customers until the order was completed. Reservations created by this option now block the seat correctly.
  • Fix: On block themes (like Twenty Twenty-Four) the public ticket page fell back to a deprecated WordPress legacy template and printed a deprecation notice — the page now renders a clean minimal shell there.
  • New: The print preview in the Kasse opens the ticket as a PDF.
  • Fix: Selling a ticket crashed with a server error when the ticket list used a code format — the format reached the code generator in the wrong shape; the generator now handles both shapes.
  • New: The Kasse area shows one button per ticket list — a single click opens the sale popup with the list preselected (switchable inside the popup), amount, payment note and customer name.
  • New: Sell tickets directly at the counter — the new “Kasse” area issues tickets from a ticket list without a shop order, attaches an internal sale number to every ticket and confirms payment with one click. Sales can be cancelled or partially refunded; cancelled tickets are freed for reuse. Print preview opens each ticket in the browser. The sale confirmation is checked at the scanner: a ticket whose direct sale was not confirmed yet does not redeem.

3.2.0 – 2026-09-13

  • New: Kasse is now switchable (default on) — turn the whole Kasse tab off as a safety stop or for handheld-only shops.
  • New: The Kasse ticket-list overview is switchable (default on) — disable to open the sale popup directly on touch screens.
  • New: The Kasse orders table now uses server-side DataTable processing (search / paging / sorting), status pills, and per-row Confirm / Cancel / Refund / Partial refund / Print tickets actions. Filtering and ordering are handled on the server.
  • New: Filter the ticket list by scanner account — new search filter “AUTHTOKEN:” shows all tickets redeemed by one ticket scanner (enter the id shown in the scanner details), so you can review each entrance team member’s activity without opening every ticket.
  • New: The scanner makes a successful read unmistakable — the camera area lights up with a green frame (like card payment terminals) and a clear “code read, waiting for server” message the moment a QR code is recognized, followed by a short deliberate pause before the next scan is processed. Queued scans of group members are never lost and keep their order.
  • Fix: The ticket scanner silently dropped scans that arrived while the previous ticket was still loading (slow Wi-Fi, fast consecutive scanning of groups) — those guests were never redeemed in the dashboard. Scans are now queued and processed one after another, with a short on-screen note.
  • Fix: Re-scanning a ticket that this scanner redeemed moments ago showed a red “ticket already used” error — confusing operators at the entrance. The scanner now recognizes its own successful redeems and shows a calm green confirmation instead.
  • Fix: The same seat could be sold twice — a second order (or a double add-to-cart with the same seat) confirmed a seat that already belonged to another order, creating two paid tickets for one seat while the seat map only showed one sale. A seat already confirmed for another order is now refused, and a selection containing the same seat more than once is rejected at add-to-cart with a clear message.
  • Fix: When an order was refunded or cancelled, the freed tickets kept a user registration from the previous buyer — the old owner stayed visible on the ticket and could interfere with its next use. Registrations are now cleared together with the other order information, and when a ticket is reused for a new purchase, any leftover registration or usage information is swept automatically.
  • New: Tickets without WooCommerce — the big decoupling step. Ticket lists, ticket numbers, PDF tickets and the ticket scanner now work without a WooCommerce order behind them, for printed cards you hand out yourself. (Details follow with the release.)
  • New: The PDF path for tickets without an order — the single ticket PDF, the ticket page and the bulk “one PDF” print sheet now render order-less tickets instead of failing with an order error. The ticket shows its own number, its list, the QR code and the redemption state; everything that normally comes from the order (customer, purchase dates) stays empty. With the “allow tickets without order” switch off, everything behaves exactly as before.
  • Fix: Order-related errors (#7001/#7002/#8010/#8013/#8020/#8021) no longer appear for tickets that are deliberately allowed to have no order.
  • New: The setup wizard now asks whether you will sell or hand out tickets directly, without a WooCommerce order — at the door, by invoice or as printed cards — and explains what the switch does. The option’s description in the settings was extended the same way.
  • New: The admin area formerly known as “Congresses” is now the “Event App” — the companion page your visitors open with their ticket (programme, speaker info, downloads, support pages; for a congress just as much as for a single event). Each app row has an “Open example” button that opens the visitor view in a new tab, using one of the app’s real tickets. The button appears once a ticket exists.
  • Tweak: The support info block now reads “Tested up to”, “Requires at least” and “Requires PHP” live from readme.txt instead of carrying hardcoded values that lagged behind (it showed 6.9 while the readme said 7.1).
  • New: The setup wizard has a fifth use case, “Direct sales — no WooCommerce” — for tickets you sell at the door, by invoice or as printed cards. It switches the without-order path on and carries scanner defaults instead of order-processing options. When WooCommerce is not installed, this use case is preselected automatically.
  • Tweak: The “Allow tickets without a WooCommerce order” setting now lives in its own section, “Direct sales (no WooCommerce order)”, instead of deep inside the WooCommerce sales section — easier to find, especially on sites without WooCommerce. Nothing about the option itself has changed.

3.1.14 – 2026-09-07

  • Security: Added nonce verification to the admin-area AJAX endpoint (executeWCBackend) to block cross-site request forgery. The frontend already shipped the nonce; the server now verifies it.
  • Security: Restricted WooCommerce order/product data actions (downloadTicketInfosOfProduct, downloadAllTicketsAsOnePDF, removeAllTicketsFromOrder, removeAllNonTicketsFromOrder, downloadPDFTicketBadge) to users with the manage_woocommerce or edit_shop_orders capability. Without this, a low-privilege role granted admin-area access via the “Allow only specific roles” setting could read or delete every customer’s ticket data through the plugin-internal role check.
  • Security: Removed an eval(data) call after $.getScript() in the seating-admin loader (backend.js, _displaySeatingplanArea, line 1288). $.getScript() already executes the loaded script; the extra eval ran every byte of the response through the JS engine again. CWE-95 — a server-side change to js/seating_admin.js would have given code-injection on every admin page that opens the seating-plan area. No callers, no behaviour change beyond the redundant execute.
  • Security: Ticket codes, scanner auth tokens and ticket idcodes are now generated with a cryptographically secure random source (random_bytes) instead of a hash of the current time (md5(time() ...)). The old values were predictable: two codes created in the same second shared their time component, so anyone who knew roughly when a ticket was issued could narrow the guessing range dramatically. CWE-338. Five generators were changed — the ticket code and the code-list lock in the WooCommerce assignment path, the per-list and per-order idcode, and the ticket-scanner auth token. The printed format is unchanged (same length and character set), existing tickets and tokens keep working, and no migration is needed.

3.1.13 – 2026-09-03

  • Tweak: Products with variations no longer show the seat selector on the shop overview page. In the overview no variation is chosen, so the selector could not work there anyway – it only pushed the product image out of its card. The “Select options” link leads to the product page, where the full seat selection (and its validation) lives. Simple products keep the quick selector in the overview.

3.1.12 – 2026-09-02

  • Tweak: The premium wizard now says exactly what the “Enable Recommended Settings” button does before you click it: attach tickets as PDF to the purchase email, merge all tickets of an order into one PDF, and raise the attachment limit to 21. Previously the popup only vaguely asked to “enable PDF ticket attachment” and revealed the actual settings only after they had already been changed.
  • Tweak: “Skip” in the premium wizard closes the popup instantly instead of waiting for the server. The “don’t show again” marker is written exactly once per installation – the first time the wizard is skipped while it is still unset; re-opening the wizard later sends no request at all.
  • Fix: In multilingual shops (WPML), the seat check on “add to cart” was silently skipped when the customer bought in a secondary language. The check read the seat settings from the translated product, where they do not exist – a shop could sell numbered-seat tickets without a chosen seat. The check now reads the settings from the original product, like the cart display already did.
  • New: A safety net at checkout. If a product with required seat selection reaches the cart or checkout without a seat on its line – possible when the seating plan was still unpublished at add-to-cart, when a seat reservation expired and was removed, or when another plugin rewrote the cart – the order is now blocked with a clear message until a seat is selected. Products with optional seats are unaffected.

3.1.11 – 2026-09-01

  • Fix: Adding a ticket with a chosen seat to the cart failed with “Invalid seat selection” on every attempt since 3.1.8. The seat check compared the chosen seat against a value that the variation-plan rework had left behind, so no seat could ever pass – on products with and without variations. Valid seats are accepted again.

3.1.10 – 2026-08-31

  • Fix: Two errors that blocked a shop after a staging-to-live database migration. (1) The Event Tickets admin page stayed on the loading spinner and showed “#505 auth token not found” as soon as a ticket in the list referenced a scanner token that no longer existed in the new database – the audit column tried to read the token’s name and the missing-row error crashed the whole page. (2) Membership products that were never ticket products suddenly demanded a “ticket or access code” in the cart and at checkout, even though their product settings showed no restriction. Both came from values that the database carried over from staging. (1) is caught and falls back to “AUTHTOKEN DELETED” in the audit column; the migration artefact no longer breaks the page. (2) sits behind the same is_ticket gate that already protects the other ticket-specific cart fields (added in 3.1.8): a stale restriction on a non-ticket product is now ignored, both for the input field and for the checkout validation. The restriction still works as before for real ticket products, including variations, where the parent is walked up first.

3.1.9 – 2026-08-26

  • Fix: The “Check License” button in the settings did nothing since 3.1.6 – it showed “Checking…” forever and never contacted the license server, and after saving a license key the page never confirmed the activation. A helper function used by the button was defined in a place the button could not see, so the click stopped with an error before the request was sent. Your license was still checked in the background as before – only the visible check and the confirmation after entering a new key were dead. Moving the helper where every part of the settings page can use it brings both back.

3.1.8 – 2026-08-26

  • New: Fields that another plugin adds to an order line – for example the answers of a product add-on plugin – can now be shown as a column in the ticket list. Switch on “Display a column with the extra fields of the order line” in the settings. Until now those answers were only visible by opening each order, which is why shops with more questions than our two per-ticket fields had to build their own list. A second setting hides individual fields by name, for answers that belong in the order but not in a list. The values belong to the whole order line, not to a single ticket: an order line for three tickets carries one set of answers.
  • Fix: A seating plan assigned to a single variation is now actually used in the shop. The product editor has offered a “Seating Plan Override” per variation for a while and saved it correctly, but the shop only ever read the parent product: the seat map on the product page never changed when a customer picked another variation, the cart notice and the seat check when adding to cart used the parent’s plan as well. Picking a variation now swaps the map to that variation’s plan, and a product whose plan only exists on its variations shows a map at all for the first time. Products without variations are unaffected.
  • Tweak: In the variations of a ticket product, the label “This variation is NOT a ticket product” no longer sticks to its checkbox. It now keeps a fixed gap, so the line reads as a label and a box instead of one run-on word.
  • New: For plugin developers: fields that your plugin collects at checkout can be listed inside Event Tickets, right where our users write their ticket template. Fill the filter saso_eventtickets_template_order_fields with your fields – key and name are enough – and shop owners no longer have to look up a meta key in the database to print your field on a ticket. The heading above them is your plugin name, taken from the plugin your callback lives in; give your own heading once as the array key if you prefer. Fields of different providers are never merged, not even when two of them pick the same heading. Reading the value itself never needed us: a ticket template prints any order meta with {{ ORDER.get_meta(“your_key”) }}. The list sits under the replacement tags on the options page and stays empty until a plugin registers something – if yours is missing, ask its provider.
  • New: A new setting decides from which order status a seat counts as sold: “Mark seats as sold from this order status”. Until now a seat only turned red when the ticket number was created, which is when the order is paid – with a cash voucher or a bank transfer that can be days later, and until then the seat stayed available for everyone else. Set the status to “pending payment” and the seat is gone the moment the order is placed, while the ticket still follows on payment. The default keeps the previous behaviour. The ticket number is written onto the same seat afterwards, so cancelling an order still frees it.
  • Fix: A seat now turns red on the seat map when the order is paid, even if the customer took their time or paid later. Selecting a seat reserves it for a while – by default a quarter of an hour – and the plugin marked exactly that reservation as sold when the order was completed. If the reservation had run out in the meantime, and it always has when payment arrives days later through a cash voucher or a bank transfer, there was nothing left to mark, and the plugin treated that as done. The order carried the seat correctly, the seat map kept offering it to everyone else, and the same seat could be sold twice. The sale is now written to the seat map in any case, and a second run of the ticket creation cannot enter the same seat twice. Shops with instant card payment were affected as well whenever a checkout took longer than the reservation.
  • Fix: A one-day event no longer prints its date twice on the ticket. When no end date is entered, the plugin fills in the start date internally so the ticket stays valid until the end of the event day – and the printed date treated that filler like an entry, so “12.09.2026 19:00” became “12.09.2026 19:00 – 12.09.2026”. Only the date you actually entered is shown now: a start alone stays a start, a real end date still produces a range, and an end time on the same day still shows as “19:00 – 23:00”. The same applies to the date picker: a ticket for a chosen day shows that day once instead of “15.06.2026 19:00 – 15.06.2026”. For template authors: TICKET.end_date is never empty for the same reason, so testing it tells you nothing. Two new variables do: TICKET.is_end_date_set and TICKET.is_end_time_set.

3.1.7 – 2026-08-24

  • Fix: Removing a single ticket number from an order left that number on the order line. The number was freed in the ticket list, but the order, the email and the invoice PDF kept showing it, and it no longer lined up with the public ticket numbers next to it. The number was compared in its internal spelling against the one printed on the order, which never matched, so nothing was ever removed. Orders with several tickets on one line are the ones affected.
  • New: For developers: the decision whether an order line gets a ticket now lives in one place and can be overruled with the filter saso_eventtickets_wc_order_item_is_ticket. It exists for shops where another plugin splits one product into several order lines – split VAT or invoicing plugins – so that only the original line carries the ticket while the other lines stay bookkeeping. Nothing changes unless the filter is used.
  • New: For developers: the order manager now answers, per order line, how many ticket numbers a line is supposed to carry and which lines are still short of them (getExpectedTicketAmountForItem, countOrderItemsWithMissingTicketnumbers, orderNeedsTicketNumbers). Ticket creation uses the same calculation, so a tool that looks for missing numbers and the code that draws them can no longer drift apart. The premium bulk assignment is the first user.
  • New: The ticket export now has its own column for the value you ask per ticket (the product setting “Request a value for each ticket from dropdown”). Until now only the name per ticket had one, so the answer was in the export but buried inside the raw meta column, where a spreadsheet cannot filter or sort it. The column stays in the file even when a product does not ask for a value, so the header does not change from export to export.
  • Tweak: An extra safeguard so a product that is not configured as a ticket can never receive a ticket number, not even when it sits in the same order as tickets. Selling through the shop was never affected – the check was already made for every single order line – but the entry point that other code (the premium plugin, custom code) can call did not make it itself. It does now.

Older entries are archived in changelog.txt shipped with the plugin.