Create .ics calendar files from WordPress posts & custom post types

For websites that feature events, either through plugin or custom post type, it might be important to allow user to download individual.ics calendar files (Outlook, Google Calendar, iCalendar). Often, plugins provide the .ics generation functionality built-in, other times they require that you purchase an add-on... now you can do it yourself!

wordpress ics calendar

For websites that feature events, either through plugin or custom post type, it might be important to allow user to download individual.ics calendar files.
ICS files can be opened in pretty much any calendar management app or software, like Outlook, Google Calendar and iCalendar.
Often, plugins provide the .ics generation functionality built-in, other times they require that you purchase an add-on… now you can do it yourself!

Copy and paste this script in your theme’s functions.php file and edit the parts that you need to customize:

Make sure that you read carefully through the code, especially the part with the date vars, location, organizer etc. so that your events are fully represented in the users’ calendar.

I personally like to use Types or Custom Post Type UI, to manage custom post types, custom taxonomies and custom fields, so a practical example in that case would be:

$start_date = date_i18n("Ymd\THis\Z", get_post_meta( get_the_ID(), 'wpcf-start_date', true ));
$end_date = date_i18n('Ymd\THis\Z', get_post_meta( get_the_ID(), 'wpcf-end_date', true));
$deadline = date_i18n('Ymd\THis\Z', get_post_meta( get_the_ID(), 'wpcf-deadline_date', true)-24, true);
$location = types_render_field("location", array('output' => 'raw'));
$city = types_render_field("city", array('output' => 'raw'));
$street = types_render_field("street", array('output' => 'raw'));
$address = $location.' - '.$street.', '.$city;

[mt]

So, once looping through your posts, all you have to add is a link or button to the custom endpoint, carrying the post ID in the url parameter, like this:

<a href="<?php echo get_feed_link('calendar'); ?>?id=<?php echo get_the_ID(); ?>"> Download .ics </a>

The user will then be able to download and open the .ics file in whatever calendar app / software they want.

Now, why not pairing this cool feature with a handy weekly calendar for WordPress?

Jany Martelli · Shambix

Written by the Shambix engineering team: custom apps, AI agents, WordPress & WooCommerce, cloud and private AI since 2009.

Jany Martelli builds the systems behind digital businesses: cloud architecture, e-commerce platforms, and AI agents that do real work. 17+ years and 250+ projects at Shambix, for teams from Xiaomi to Hilton. Computer scientist, professor, and creator of Patcherly, the AI that fixes production bugs on its own.

WordPress and WooCommerce

Have a project in mind? Let's build it right.

Tell us about your goals and your budget. From a quick WordPress fix to a full custom platform, we’ll take care of the rest.

  • A senior engineer reads every brief
  • If we are not the right fit, we say so
  • info@shambix.com
Name
We work with flexible budgets, and welcome all kinds of projects, small to massive. It helps us tailor the best solution to your specific needs.

We usually reply within 24 hours. No newsletter, no spam.

Comments

  1. Luka Vilaj says:

    Hi there

    I’m not getting correct start date and end date. I’m trying to grab it from custom fields.

    $start_date = date_i18n(“YmdTHisZ”, get_post_meta( $post->ID , ‘event_start_date’, true )); // EDIT THIS WITH YOUR OWN VALUE
    $end_date = date_i18n(“YmdTHisZ”, get_post_meta( $post->ID , ‘event_end_date’ , true )); // EDIT THIS WITH YOUR OWN VALUE

    Could you advise if this is correct

    1. Jany says:

      Please share the value of your get_post_meta( $post->ID , 'event_start_date', true ));

      1. Sebo says:

        Hey, I am working currently on a similar problem. Looks like we have to change the time format to make it work. My post meta is: KeyValue
        event-date’1.12.2018′ (so the format is dd.mm.yyy) How can we change it to the needed YmdTHisZ Format?

        1. Jany says:

          The function date_i18n(); requires a UNIX timestamp, so if you use an already formatted date, it won’t work.
          https://codex.wordpress.org/Function_Reference/date_i18n

          Also, keep in mind, that calendars require a time, hence the mandatory format YmdTHisZ .
          So for the start date 1 feb 2018 22:45:00, the result should be 20180201T234500Z.
          https://php.net/manual/en/function.date.php

          You will not be able to convert your dates to calendar format without a time (or you can set a fixed one every time, if that works with the event).

          Also you will need the date to have 2 numbers for day and month (you can convert the date easily to another format with php though).

  2. kingkool68 says:

    This works. If you need something a little more flexible you might want to look at a full-featured library like https://github.com/iCalcreator/iCalcreator

  3. Benjamin Schmid-Lanz says:

    Hey! Thx for the tutorial! I actually get a ICS-File, which various programs can read, but not Google. I changed the Code a little bit since i dont need end dates, do you have any idea why?

    “BEGIN:VCALENDAR
    VERSION:2.0
    PRODID:-//Mundwerk Kulturbiotop //NONSGML Events //EN
    CALSCALE:GREGORIAN
    X-WR-CALNAME:Mundwerk Kulturbiotop

    BEGIN:VEVENT
    CREATED:20170508T190007Z
    UID:904
    DTSTART;VALUE=DATE-TIME:20170513T200000Z
    DTSTAMP:20170511T183659Z
    LOCATION:Doerflistrasse76
    DESCRIPTION:
    SUMMARY:Benefizkonzert für Smiling Gecko
    ORGANIZER:Mundwerk
    URL;VALUE=URI:https://mw-club.ch/event/benefizkonzert-fuer-smiling-gecko/
    TRANSP:OPAQUE
    BEGIN:VALARM
    ACTION:DISPLAY
    TRIGGER;VALUE=DATE-TIME:
    DESCRIPTION:Reminder for Benefizkonzert für Smiling Gecko
    END:VALARM
    END:VEVENT

    END:VCALENDAR

    “

    1. Jany says:

      I would get rid of white spaces / empty lines, to begin with. Do you get a specific error when importing?

  4. Jameson Nuss says:

    Any advice on how to implement this with Advanced Custom Fields? I keep generating a blank ics file. Any help is appreciated. Thanks!

    1. Jany says:

      The blank ics sounds like there’s an error at some point before/during the session.
      ACF fields shouldn’t be too different honestly. It’s possible that date fields are saved in a different way though.
      I’d start debugging each field in the single post, to begin with. Just echo them normally and see what they output (from line 43 to 56 of the gist).
      Feel free to paste the results here.
      Also, do you have php errors on?

      1. Jameson Nuss says:

        Another note: currently, advanced custom fields outputs the date as: December 5, 2016 11:00 am.