VE Events WP Registry grade A. No security issues foundWP RegistryNo security issues foundOpen the reportA
VE Events - A lightweight WordPress Events custom post type plugin with Schema.org markup, JetEngine/Elementor support, and multilingual capabilities.
Install
Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/hau-git/ve-events-wordpress-plugin/releases/download/v2.4.0/ve-events-wordpress-plugin.zipA lightweight WordPress Events plugin with an interactive admin calendar, native admin UI, Schema.org markup, Open Graph tags, iCal import and export, and first-class support for Elementor and JetEngine.
Version: 2.4.0 · Requires: WordPress 6.4+, PHP 8.3+
Table of Contents
- Features
- Post Type & Taxonomies
- Stored Meta Keys
- Virtual Meta Keys
- Query Variables
- Settings
- Admin Interface
- iCal Import
- ChurchDesk Import
- iCal Export
- Schema.org & SEO
- Elementor Dynamic Tags
- JetEngine Integration
- REST API
- PHP Usage Examples
- Auto-Updates
- Debugging
Features
- Custom post type
ve_eventwith 4 taxonomies (Category, Location, Topic, Series) - Date & Time form rendered directly below the post title (above the content editor)
- Live date/time preview while editing
- All-day events, hide-end-time flag, event status (Cancelled, Postponed, …)
- Organizer, ticket price/currency/availability, and attendance mode (offline/online/mixed) fields
- 20+ virtual meta keys for formatted output — usable in JetEngine, Elementor, PHP, REST
- Frontend scope filtering: upcoming / ongoing / past / archived
- Advanced query filters: date range, month, time-of-day, weekday
- Schema.org
EventJSON-LD witheventStatus,eventAttendanceMode, location/VirtualLocation, organizer, performer, priced offers, EventSeries - Open Graph / X Card meta tags (auto-detects conflicting SEO plugins)
- Category color system — CSS custom properties output in
wp_head - iCal/ICS feed importer with cron scheduling and admin log viewer
- ChurchDesk importer (Pull API + Calendar View) with full field mapping
- iCal export — per-event "Add to Calendar"
.icsdownload and a subscribable feed - Interactive backend calendar — AJAX month navigation, event popover, click-to-create, drag-and-drop rescheduling
- 7 Elementor dynamic tag types
- Backend list view: month grouping, filter bar, sortable "When" column
- German translation included (
.po/.mo) - Auto-updates from GitHub releases
Post Type & Taxonomies
Post type: ve_event
- Public, REST-enabled (
rest_base: events) - Supports: title, editor, excerpt, featured image, revisions
- Archive slug: configurable (default:
events) - Single slug: configurable (default:
event)
| Taxonomy | Key | Type | Term Meta |
|---|---|---|---|
| Categories | ve_event_category |
Hierarchical | ve_category_color (hex) |
| Locations | ve_event_location |
Flat | ve_location_address, ve_location_maps_url |
| Topics | ve_event_topic |
Flat | — |
| Series | ve_event_series |
Hierarchical | — |
Stored Meta Keys
All timestamps are UTC Unix integers. Private keys (underscore prefix) are stored in wp_postmeta.
| Meta Key | Type | Description |
|---|---|---|
_vev_start_utc |
int | Start timestamp (UTC) |
_vev_end_utc |
int | End timestamp (UTC) |
_vev_all_day |
bool | All-day event flag |
_vev_hide_end |
bool | Hide end time in frontend listings |
_vev_speaker |
string | Speaker / host name |
_vev_special_info |
string | Additional notes (admission, dress code, …) |
_vev_info_url |
string | Info or ticket URL |
_vev_event_status |
string | Status override: cancelled · postponed · rescheduled · movedOnline · "" |
_vev_organizer |
string | Organizer name |
_vev_organizer_url |
string | Organizer URL |
_vev_price |
string | Ticket price (numeric string; 0 = free; "" = unknown) |
_vev_price_currency |
string | ISO 4217 currency code, e.g. EUR |
_vev_availability |
string | Offer availability: InStock · SoldOut · PreOrder · "" |
_vev_attendance_mode |
string | Attendance mode: online · mixed · "" (offline) |
_vev_start_hour |
int | Auto-synced: start hour in site timezone (0–23) |
_vev_weekday |
int | Auto-synced: ISO weekday (1=Mon … 7=Sun) |
_vev_start_hour and _vev_weekday (plus _vev_start_date, _vev_start_month, _vev_time_slot) are automatically written whenever _vev_start_utc changes — including via calendar drag-and-drop and quick-create.
Virtual Meta Keys
Computed at runtime — not stored in the database. Available in JetEngine field queries, Elementor dynamic tags, PHP get_post_meta(), and the REST API.
Date & Time
| Key | Description | Example |
|---|---|---|
ve_start_date |
Formatted start date | 14.06.2025 |
ve_start_time |
Formatted start time | 19:00 |
ve_end_date |
Formatted end date | 14.06.2025 |
ve_end_time |
Formatted end time | 22:00 |
ve_date_range |
Smart date range | 14.06.2025 / 14.–16.06.2025 |
ve_time_range |
Time range or "All day" | 19:00 – 22:00 |
ve_datetime_formatted |
Full date + time | 14.06.2025, 19:00 – 22:00 |
Status
| Key | Description | Example |
|---|---|---|
ve_status |
Timeline status | Upcoming / Ongoing / Past / Archived |
ve_is_upcoming |
Boolean | true / false |
ve_is_ongoing |
Boolean | true / false |
ve_is_cancelled |
Boolean | true / false |
ve_event_status_label |
Human-readable override status | Cancelled / Postponed / … |
ve_event_status_color |
Hex color for status badge | #d63638 |
Taxonomy
| Key | Description |
|---|---|
ve_location_name |
First assigned location term name |
ve_location_address |
Location address (term meta) |
ve_location_maps_url |
Maps URL — custom or auto-generated from address |
ve_category_name |
First assigned category term name |
ve_category_color |
Category hex color (term meta) |
ve_category_class |
CSS class name, e.g. ve-cat-workshop |
ve_series_name |
First assigned series term name |
ve_topic_names |
Comma-separated topic names |
Offer & Export
| Key | Description | Example |
|---|---|---|
ve_price_formatted |
Formatted price with currency (Free when 0) |
12,00 EUR |
ve_ical_url |
Per-event .ics download URL ("Add to Calendar") |
https://site.tld/?vev_ics=123 |
Query Variables
Use these in WP_Query args or as URL parameters on frontend archive/listing pages.
| Variable | Values | Description |
|---|---|---|
vev_event_scope |
upcoming · ongoing · past · archived · all |
Filter by event timeline state |
vev_include_archived |
0 · 1 |
Include archived events in results |
vev_date_from |
Y-m-d or UTC timestamp |
Events starting on or after this date |
vev_date_to |
Y-m-d or UTC timestamp |
Events starting on or before this date |
vev_month |
YYYY-MM |
Events in a specific month |
vev_time_from |
0–23 |
Events starting at or after this hour |
vev_time_to |
0–23 |
Events starting at or before this hour |
vev_weekday |
1–7 or "1,3,5" |
Events on specific ISO weekday(s) |
Scope definitions:
upcoming— start > nowongoing— start ≤ now AND end ≥ nowpast— end < now but within grace period (in hours)archived— end older than grace periodall— no timeline filter
// Show only upcoming events
$query = new WP_Query( [
'post_type' => 've_event',
'vev_event_scope' => 'upcoming',
'posts_per_page' => 10,
] );
// Events on Friday evenings in June 2025
$query = new WP_Query( [
'post_type' => 've_event',
'vev_month' => '2025-06',
'vev_weekday' => '5',
'vev_time_from' => 18,
] );
Settings
Events → Settings in the WordPress admin.
| Setting | Default | Description |
|---|---|---|
slug_single |
event |
URL slug for single event pages |
slug_archive |
events |
URL slug for the event archive |
disable_gutenberg |
false |
Use Classic Editor instead of Gutenberg |
hide_end_same_day |
true |
Hide end date when start and end are the same day |
grace_period |
24 |
Hours to keep showing events after they end. Options: 0 (hide immediately) · 1 · 2 · 4 · 6 · 12 · 24 (1 day) · 72 (3 days) · 168 (7 days) · 999999 |
hide_archived_search |
true |
Exclude archived events from WordPress search |
include_series_schema |
true |
Add EventSeries superEvent to Schema.org output |
output_category_colors |
true |
Output category color CSS variables in wp_head |
og_tags |
auto |
Open Graph output: auto · always · disabled |
ical_feed |
true |
Expose the subscribable iCal feed of upcoming events |
series_suggestions |
false |
Show series auto-suggestion UI when editing events |
Admin Interface
Event Edit Page
The event form is rendered directly below the post title, before the content editor, so date and time are always the first thing you fill in.
Date & Time (always visible):
- Start date + time, End date + time
- All-day checkbox (disables time inputs)
- Hide end time checkbox
- Live preview: updates in real-time as you type
Details (WP metabox — below content editor by default, draggable):
- Speaker / Host
- Info / Ticket URL
- Organizer + Organizer URL
- Tickets & Offer: Price · Currency · Availability
- Additional Notes
Event Status (sidebar metabox — below Publish):
- Scheduled (default) · Cancelled · Postponed · Rescheduled · Moved Online
- Attendance Mode: Offline (default) · Online · Mixed
- Updates Schema.org
eventStatus/eventAttendanceModeand shows a badge in the event list
Event List
- Views: Upcoming · Past · All · Drafts · Trash · Calendar
- Columns: Title · When · Category · Location · Topic
- Month grouping: Visual separator rows between months
- Filter bar: Month · Category · Location · Topic dropdowns
- Sortable: "When" column sorts by start date
Interactive Calendar Grid
Accessible via the Calendar tab in the event list — a monthly grid (week starts Monday) with color-coded event pills. Fully interactive, with a progressive-enhancement fallback when JavaScript is disabled:
- AJAX month navigation — Previous / Next switch months without a page reload, with browser history support (the back button works); falls back to normal links without JS
- Event popover — click an event to see its time, location, category, and status with Edit / View buttons
- Click-to-create — click an empty day to open a quick-create popover (title, start/end time, all-day) and save as draft or publish
- Drag-and-drop rescheduling — drag an event onto another day to move it; the local wall-clock time and multi-day span are preserved (DST-safe), and the denormalized filter fields stay in sync automatically
- Draft events appear on the grid (dimmed); cancelled events are struck through
Taxonomy Forms
Category edit page: Color picker field — stored as hex, output as CSS custom property.
Location edit page: Address and Google Maps URL fields. Maps URL is auto-generated from the address if left empty.
iCal Import
Events → Import Feeds — import events from any iCal/ICS feed (Google Calendar, Outlook, etc.).
- Add a feed URL and configure the import schedule
- Supported intervals: every 15 min · every 30 min · daily · weekly
- Field mapping: map iCal properties (SUMMARY, DTSTART, LOCATION, …) to event fields
- Run Now button for manual import
- Import log viewer with per-run success/error details
- Cron is automatically scheduled on feed publish and cleared on trash/delete
ChurchDesk Import
Events → Import Feeds → set Source Type to ChurchDesk to import events from a ChurchDesk organization. ChurchDesk feeds reuse the same scheduling, update modes, delete-on-removal, default-taxonomy and log features as iCal feeds.
Two endpoints are supported (selectable per feed):
| Endpoint | URL | Auth |
|---|---|---|
| Pull API | https://api.churchdesk.com/v3.0.0/events |
organizationId + partnerToken |
| Calendar View | https://api2.churchdesk.com/collaboration/calendar-view |
organizationId |
The Pull API is the documented, versioned integration API; request a
partnerToken from support@churchdesk.com. The Calendar View endpoint is
the public portal/embed source and needs only the organization id. (The
calendar-view response shape is not part of the published API contract, so its
fields are mapped defensively.)
Field mapping
| ChurchDesk field | VE Events target |
|---|---|
id |
import key (_vev_import_uid) |
title |
post title |
description |
post content |
summary |
excerpt |
startDate / endDate |
_vev_start_utc / _vev_end_utc (UTC) |
allDay |
_vev_all_day |
showEndtime |
_vev_hide_end (inverted) |
contributor |
_vev_speaker |
price |
_vev_special_info |
categories[] (with color) |
Category taxonomy (+ ve_category_color) |
locationName + locationObj |
Location taxonomy (+ ve_location_address) |
image |
Featured image (optional, via media sideload) |
updatedAt |
change-detection timestamp |
Per-feed options: an optional comma-separated category id filter, whether to
import the event image as the featured image, and the image format (free text;
e.g. span6_16-9 for Calendar View, span7_16-9 for the Pull API). The resources and
parishes fields are not imported.
Imported images are de-duplicated: events that share the same image reuse a single attachment (matched on the ChurchDesk media id, with the filename as a fallback) rather than uploading a copy each. Each imported image also gets alt text from the event title when it has none.
Cross-feed merge
If you import the same events from more than one feed — for example the ChurchDesk iCal
export and the ChurchDesk API of the same organization — enable Cross-feed merge
on a feed (under Import Behaviour). Instead of creating a duplicate, the importer matches
the existing event on the ChurchDesk event id (embedded in the iCal UID/URL, with a
start-time + title fallback) and enriches it with the other feed's data — above all the
featured image. Enrichment is additive: it only fills empty fields and a missing image,
never overwriting the title, content, dates, or values another feed already set. Matching is
order-independent (whichever feed imports first owns the event; the other enriches it).
iCal Export
The plugin serves standards-compliant (RFC 5545) .ics output — the outbound counterpart to the importers. No configuration is required for single-event downloads; the subscribable feed is toggled by the ical_feed setting (enabled by default).
Per-event download ("Add to Calendar")
Every published event exposes a .ics download at:
https://your-site.tld/?vev_ics=<event_id>
The URL is also available as the virtual field ve_ical_url, so you can drop an "Add to Calendar" button into an Elementor / JetEngine template or a theme:
$ics = get_post_meta( get_the_ID(), 've_ical_url', true );
printf( '<a class="button" href="%s" download>Add to Calendar</a>', esc_url( $ics ) );
Subscribable feed
A live feed of all upcoming (and ongoing) events:
https://your-site.tld/?vev_ics=feed # https
webcal://your-site.tld/?vev_ics=feed # one-click subscribe in Apple/Google/Outlook
https://your-site.tld/?vev_ics=feed&vev_ics_cat=<category-slug> # filtered by category
- Unlike a one-off download, the feed stays in sync — calendar apps re-poll it periodically.
- Responses send
ETag/Last-Modifiedand answer conditional requests with304 Not Modified, so repeated polling is cheap. - The exact feed and subscribe URLs are shown under Events → Settings → Schema & SEO when the feed is enabled.
VEVENT output includes UTC times (or VALUE=DATE for all-day events, with the RFC-correct exclusive end date), SUMMARY, DESCRIPTION, LOCATION (name + address), URL, a UID stable per post, STATUS (mapped from the event-status override), and ORGANIZER when an organizer URL is set.
Schema.org & SEO
Schema.org JSON-LD
Output on single event pages (`
Releases
14 releases. Each count is every asset in that release; expand a row for the breakdown.