Events is a full-featured Craft CMS Plugin for event management and ticketing. Events integrates with Craft Commerce so you can easily sell tickets to your events.
Events requires Craft CMS 2.6 or higher.
Events extends und uses Craft Commerce features. The minimum version of Craft Commerce needed is 1.2.
Events requires Craft PHP 5.4 or higher.
Installing Events is as simple as any other Craft plugin - just drop the events/
folder in your craft/plugins
directory and install.
events/
directory into your craft/plugins/
directory.With Events installed, you will be able to acess the plugin settings. Here you can enter the license key for using Events and get access to general settings.
In the General Settings section you can adjust the length of the generated ticket SKU. Ticket SKU's are generated automatically when you add A Ticket Type to an event and when this ticket get purchased. Per default it is set to 6 characters length.
With Events now installed, you have to setup first:
Then you can create Events for your created event type.
Refer to the Releases via our Github repository for all updates and changes.
Go to the main section of Events via the CP sidebar menu. Because events are handled as element types, you will be presented a list similar as the entries overview.
Before you can start creating events first you have to set up a Event Type and a Ticket Type.
The overview shows a list of all events. You can filter them via event types or status and can search via their title. Also supported is a quick edit of the event details via double click at the status icon next to the event title.
Each field is fairly self-explanatory, but any additional information is provided below.
Events can show a live preview of you currently editing event. This is only possible, if you marked Events of this type have their own URLs the Event Type settings and provided a Event URL Format as well as a Event Template. Read further details under the Event Type section.
The Share button allows you to share a draft version of the event. If the event is not live yet, the link contains a token which allows you to show the event detail page. Without the token the event detail page is shown as page not found. This ability allows you to share the event link internal to get an approval or similar before you publish the event.
Here you can find a table list of all created event types. First step(s) to start is to create your first event type you can categories events for.
The Delete icon deletes already created event types. Created events for this event type will also be deleted. Already purchased tickets still remain in the database.
Each field is fairly self-explanatory, but any additional information is provided below.
If you ticked Events of this type have their own URLs, the following fields appear:
If you ticked it up, you should create a template file and insert the path. You can find a template example in the Templating section.
Event Fields are provided to use custom fields for events. You can find more details under the Event Custom Fields section.
Here you can find a table list of all created ticket types. First step(s) to start is to create your first ticket type you can create tickets for.
The Delete icon deletes already created ticket types. Created tickets for this ticket type will also be deleted. Already purchased tickets still remain in the database.
Each field is fairly self-explanatory, but any additional information is provided below.
If you ticked Tickets of this type have their own URLs, the following fields appear:
If you ticked it up, you should create a template file and insert the path. You can find a template example in the Templating section.
Ticket Fields are provided to use custom fields for tickets. You can find more details under the Ticket Custom Fields section.
Events supports a PDF version of purchased tickets. They can be printed by the customer to use them at the entrance. This PDF feature is using the Craft CMS integated Dompdf()
function.
The printed ticket appearance is handled by a html template. You need to create a new template file somewhere in you template directory. A template example is provided in the Templating section under PDF Ticket.
Add a new dynamic route in Settings -> Routes:
shop/events/ticket/<tag>/<number>
<tag>
: This is the order id where the ticket was purchased.<number>
: This is the line item id of the ticket type which was purchased.shop/events/_ticket
. You can leave off the html ending.Last but not least you have to provide a download button oder link. You can put it in your costumer/order.html
file for instance. Don't forget to use the link you pasted in your dynamic route.
<a target="_blank" href="/shop/events/ticket/{{ order.id }}">Download PDF Tickets</a>
The link has to point to the route you just created.
You can also display the download link for every single line item within you line item loop:
{% if item.purchasable.elementType == 'Events_Ticket' %}
<a target="_blank" href="/shop/events/ticket/{{ order.id }}/{{ item.id }}">Download PDF Tickets</a>
{% endif %}
Events provides a QR code generation feature. Because URL's are most times super long and not very beautiful to print we decided to use a QR code instead. The generated QR code contains a link to the Ticket Check In controller with the the ticket SKU.
Events is providing an easy ticket check in. The check in controller validates the ticket sku and checks if the ticket was already checked in to avoid multiple usage.
The route to the check in controller is following:
actions/events/ticket/checkin?sku=<sku>
<sku>
: This is the ticket SKU which gets generated automatically at the purchase of the ticket. This SKU is unique.The controller returns a json response. On an error the response contains a simple error message. On success the response contains following:
You can display a list of all events via the following template snippet:
{% for event in craft.events.events.find() %}
Events are element types. Hence they are selectable via the Craft Element Criteria Model. For instance you can set a limit vouchers via limit()
.
{% for event in craft.events.events.limit(5).find() %}
Another way to adjust your list is to specify a event type via type()
.
{% for event in craft.events.events.type('festival').find() %}
And of course, you can combine multiple criterias.
{% for event in craft.events.events.type('festival').limit(5).find() %}
Tickets are also handled as ticket types. Hence you can select them similar as events via criterias. To get all tickets for a specified event you need to add the event id.
{% for ticket in craft.events.tickets.eventId(event.id) %}
Because tickets can have a Available From
and Available To
parameter you need to be aware of this. Events provides a simple helper function to get all available tickets. The event id also needed here again.
{% for ticket in craft.events.availableTickets(event.id) %}
Purchased tickets are stored in a extra table called purchased tickets. You can get this tickets via craft.events.purchasedTickets()
. You can give this function up to 2 parameters:
Events have a maximum capacity. The capacity are calculated by the summary of the quanitites of all created event tickets. To check for the maximum event capacity you can paste in a event id as an argument.
{% set purchasedEventTickets = craft.events.purchasedTickets({ eventId: event.id }) | length %}
{% if purchasedEventTickets < event.capacity %}
// Your ticket list here...
{% endif %}
Every ticket has a maximum quantity. To check for the maximum quantity you can paste in a ticket id as an argument, similar as events.
{% set purchasedTickets = craft.events.purchasedTickets({ ticketId: ticket.id }) | length %}
{% if purchasedTickets < ticket.quantity %}
//...
{% endif %}
A simple ticket selection list can look like following snippet:
{# check for event limit #}
{% set purchasedEventTickets = craft.events.purchasedTickets({ eventId: event.id }) | length %}
{% if purchasedEventTickets < event.capacity %}
<form method="POST">
<input type="hidden" name="action" value="commerce/cart/updateCart">
<input type="hidden" name="redirect" value="shop/cart">
<input type="hidden" name="qty" value="1">
{{ getCsrfInput() }}
<select name="purchasableId" class="purchasableId">
{%- for ticket in craft.events.availableTickets(event.id) -%}
{# check for ticket limits #}
{% set purchasedTickets = craft.events.purchasedTickets({ ticketId: ticket.id }) | length %}
{% if purchasedTickets < ticket.quantity %}
<option value="{{ ticket.purchasableId }}">
{{ ticket.getTicketTypeName() }} - {{ ticket.price|commerceCurrency(cart.currency) }}
</option>
{%- endif -%}
{%- endfor -%}
</select>
<button type="submit">{{ "Add to cart"|t }}</button>
</form>
{% else %}
<strong>Sold out</strong>
{% endif %}
Events is providing a multi ticket selection list. To use it you need to call the custom frontend controller events/cart/add
.
A complete integration can look like following snippet:
<form method="POST">
{# custom frontend controller #}
<input type="hidden" name="action" value="events/cart/add">
<input type="hidden" name="redirect" value="shop/cart">
{{ getCsrfInput() }}
<table width="100%" border="0" cellpadding="0" cellspacing="0">
{% for ticket in craft.events.availableTickets(event.id) %}
<tr>
<td>{{ ticket.getTicketTypeName() }}</td>
<td>{{ ticket.price | commerceCurrency(cart.currency) }}</td>
<td align="right" nowrap="nowrap">
<input type="hidden" name="event" value="{{ event.id }}">
{# check for ticket limits #}
{% set purchasedTickets = craft.events.purchasedTickets({ ticketId: ticket.id }) | length %}
{% set availableTickets = ticket.quantity - purchasedTickets %}
{% if availableTickets > 0 %}
<div class="field dropdown">
<div class="input">
<select name="item[{{ ticket.id }}][qty]" class="ticket_table_select">
{% set maxDropdown = (availableTickets > 10) ? 10 : availableTickets %}
{% for i in 0..maxDropdown %}
<option value="{{ i }}">{{ i }}</option>
{% endfor %}
</select>
</div>
</div>
{% else %}
<strong>Sold out</strong>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<input type="submit" value="{{ "Add to cart"|t }}" class="button"/>
</form>
Purchased tickets can be displayed after the purchase in the costumer/order.html
or _pdf/order.html
file within the line item loop. Use following template snippet:
{% if item.purchasable.elementType == 'Events_Ticket' %}
{% set purchasedTickets = craft.events.purchasedTickets({ lineItemId: item.id }) %}
{% if purchasedTickets %}
{% for purchasedTicket in purchasedTickets %}
SKU: {{ purchasedTicket.ticketSku }}<br />
{% endfor %}
{% endif %}
{% endif %}
To generate a pdf ticket you need to create a extra template view. You can use simple html tags, css styling and even twig tags.
Displaying a list of all purchased tickets for an order just use:
craft.events.purchasedTickets({ orderId: tag)
<tag> is used as order id, which we defined previously in our route setup.
If you did add <number> into your route setup, you can add number
as lineItemId:
craft.events.purchasedTickets({ orderId: tag, lineItemId: number })
false
To replace a ugly URL with a beautiful QR Code, simply use:
<img src="{{ ticket.getQR() }}" />
Following template snippet can help you creating a appropiated template file:
{% set html %}
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<style>
html {
margin-top:0.2in !important;
margin-left:0.2in !important;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 13px;
line-height:1.4em;
font-weight:bold;
}
.ticket {
width:8in;
height:2.7in;
background-size:cover;
background-repeat:no-repeat;
position:relative;
margin-bottom: 0.2in;
}
#event-info {
display:inline-block;
position:absolute;
left:0.9in;
top:0.12in;
width:4.7in;
}
.label {
color:#768690;
display:block;
text-transform:uppercase;
}
.value {
display:block;
color:#121212;
text-transform:uppercase;
overflow:hidden;
font-size:16px;
}
#title {
height:0.4in;
}
#stub-info {
display:block;
position:absolute;
top:0.06in;
left:6in;
width:1.9in;
text-align:center;
}
#purchased-on {
display:inline-block;
color:#fff;
text-transform:uppercase;
font-size:9px;
text-align:center;
width:100%;
position:relative;
}
#qrcode {
position:relative;
width: 70%;
height: auto;
margin-top: 0.3in;
margin-left: -1.9in;
}
#ticket-num {
display:block;
text-transform:uppercase;
text-align:center;
width:100%;
position:relative;
top: 0;
left: 0;
font-weight:bold;
font-size: 12px;
}
#attendee-info {
text-align:left;
font-size:10px;
position:relative;
top:0.18in;
line-height: 1.6em;
}
#attendee-info .value {
font-size:10px;
}
</style>
</head>
<body>
{% set orderId = tag %}
{% for ticket in craft.events.purchasedTickets({ orderId: orderId, lineItemId: number }) %}
<div class="ticket">
<div id="event-info">
<span class="label">EVENT</span>
<span id="title" class="value">{{ ticket.getEvent().title }}</span>
<span class="label">DATE AND TIME</span>
<span class="value">{{ ticket.getEvent().startDate | date("M j, Y \\a\\t g:i A") }}</span>
<span class="label">to</span>
<span class="value">{{ ticket.getEvent().endDate | date("M j, Y \\a\\t g:i A") }}</span>
</div>
<div id="stub-info">
<span id="purchased-on">Purchased on {{ ticket.getOrder().dateOrdered | date("M j, Y \\a\\t g:i A") }}</span>
<img id="qrcode" src="{{ ticket.getQR() }}" />
<span id="ticket-num" class="value">#{{ ticket.ticketSku }}</span>
<div id="attendee-info">
<span class="label">1 {{ ticket.getTicketTypeName() }} Pass</span>
{% if ticket.getOrder().customer.user %}
<span id="name" class="value">{{ ticket.getOrder().customer.user.name }}</span>
{% else %}
{% set address = ticket.getOrder().customer.addresses[0] %}
<span id="name" class="value">{{ address.firstName }} {{ address.lastName }}</span>
{% endif %}
<span id="email" class="value">{{ ticket.getOrder().customer.email }}</span>
</div>
</div>
</div>
{% endfor %}
</body>
</html>
{% endset %}
{% set settings = {
compress: true,
orientation: 'portrait',
size: 'letter',
cacheDirectory: 'cache/tickets',
filename: 'JAF2015-' ~ orderId ~ '.pdf'
} %}
{% set pdf = craft.events.pdfFromHtml(html, settings) %}
{{ pdf.output }}
Events provides custom fields. You can assign them for Events and Tickets.
You can access this custom fields easily as every other custom field in Craft. For instance, an assigned image asset field to an event can be displayed by following template code:
<img src="{{ voucher.customFieldImage.first().getUrl() }}" />
In this case customFieldImage
is the handle of the custom field you did assign.
You can assign custom fields to events via Event Types.
Once you assigned custom fields to a event type, they appear on the Event edit page and can filled with content. Every single tab you assigned in the field layout appears as it own tab with the associated fields.
You can assign custom fields to tickets via Ticket Types.
Once you assigned custom fields to a ticket type, they appear on the Event edit page in the ticket tab under the ticket settings. To display the ticket settings simply click on the gearwheel icon. All assigned custom fields appear under the Available From/To fields.
Because tab handling is not supported here, just assign all custom fields into the same tab in the ticket type field layout editor.
Notice
After you selected a ticket type, assigned custom fields won't appear. First save the event and reopen the ticket settings, then custom fields will be displayed.
Get in touch via the Craft Community Slack and be sure to post in the #help
channel and mention our handle (@crawf
). This is the most preferred method.
If you've found a bug, or would like to make a feature request, head to the GitHub Repo and file an issue. Pull requests are also most welcome!
Get our attention on Twitter by using the #craftcms
hashtag and mentioning @verbb
Ask a question via the Craft Stack Exchange and tag your question with plugin-events
.
Any feedback, comments, questions or suggestions please email us at support at verbb.io
.