---
title: "Javascript Agenda Load Public Google Calendar Events Example | Mobiscroll"
component: "Agenda"
framework: "JavaScript"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/javascript/agenda/load-events-from-google-calendar"
---

# Load Public Google Calendar Events - JavaScript Agenda demo

Load events from a public Google Calendar into the Javascript agenda view using the integration plugin — connect with a Calendar ID and API key. Plain JavaScript API.

- [Live demo](https://demo.mobiscroll.com/javascript/agenda/load-events-from-google-calendar)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-javascript/tree/main/src/demos/eventcalendar/agenda/load-events-from-google-calendar)
- This demo in other frameworks: [jQuery](https://demo.mobiscroll.com/jquery/agenda/load-events-from-google-calendar.md), [Angular](https://demo.mobiscroll.com/angular/agenda/load-events-from-google-calendar.md), [React](https://demo.mobiscroll.com/react/agenda/load-events-from-google-calendar.md), [Vue](https://demo.mobiscroll.com/vue/agenda/load-events-from-google-calendar.md)

## Description

Event data can be loaded from remote sources, like public google calendars. Through the [**integration plugin**](https://mobiscroll.com/docs/javascript/eventcalendar/calendar-integrations) you can easily show events that are available in a public calendar. The integration plugin needs to be added to the download package or installed separately from a dedicated NPM package.

You will just need the `CALENDAR_ID` and an `apiKey` from google and you should be ready to roll.

Public calendars are read-only. If you are interested in syncing private google calendars with read/write/delete access, [check out this example](https://demo.mobiscroll.com/javascript/agenda/sync-events-google-calendar).

This example uses the [**integration plugin**](https://mobiscroll.com/docs/javascript/eventcalendar/calendar-integrations) to connect to and load events from Google Calendar and it is not available in the trial. Give the live demo a try and see how it can be configured.

## What this demo shows

- Shows a weekly agenda view with events listed and grouped by date.
- **Custom header** The current month and year are shown on the left side of the header.
- **View switching** A segmented control in the center lets users switch between `Month`, `Week`, `Day`, and `Agenda` views, with `Agenda` selected by default.
- **Secondary navigation** Blue previous and next arrow buttons are shown on the right side of the header with a `Today` button between them.
- **Week view** A week calendar is displayed at the top of the view.
- **Week navigation** The week strip can be changed by clicking and dragging left or right.
- **Day cell states** Hovering a day highlights the day number with a gray background. Selecting a day highlights the day number with a blue background. The current date is highlighted by default.
- **Event markers** Days with events show a small dot marker inside the day cell.
- **Agenda list** The area below the calendar lists events for the selected day.
- **Date selection** Selecting a day in the week calendar updates the agenda to show events for that date.
- **Events** Events appear as agenda cards with a colored strip on the left and the event title next to it. Start and end times are stacked on the right side of timed events. All-day events show the all-day label on the right.
- **Event interaction** Hovering an event highlights it.
- **Event selection** Clicking an event selects and highlights it.
- **Weekly scheduler view** Selecting the `Week` option from the segmented control switches the layout to a weekly scheduler view. This shows the days of the week at the top, an all-day section for all-day events, and a 24-hour time grid for each day of the week for timed events.
- **Daily scheduler view** Selecting the `Day` option from the segmented control switches the layout to a daily scheduler view. This shows the days of the week at the top, an all-day section for all-day events, and a 24-hour time grid for one day for timed events.
- **Scheduler view** The current time is marked with a blue line in the time grid.
- **Scheduler view** The time grid can be scrolled vertically with the mouse wheel while the header stays sticky.
- **Monthly calendar view** Selecting the `Month` option from the segmented control switches the layout to a monthly calendar view. Days with events display event labels inside the month grid cells.

## Best for

- **Google Calendar overlays** Showing events from public Google Calendars inside an agenda view.
- **Read-only event publishing** Sharing team, organization, or community calendars where visitors need to browse events but not edit them.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-themeVariant) - option
- [`setEvents`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-setEvents) - method
- [`view`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-view) - option
- [`exclusiveEndDates`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-exclusiveEndDates) - option
- [`onPageLoading`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onPageLoading) - event
- [`renderHeader`](https://mobiscroll.com/docs/javascript/eventcalendar/api#renderer-renderHeader) - renderer
- [`setOptions`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-setOptions) - method
- [`labels`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-labels) - option
- [`onInit`](https://mobiscroll.com/docs/javascript/eventcalendar/api#event-onInit) - event

## Code

### JS

```js
mobiscroll.setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

var CALENDAR_ID = 'theacidmedia.net_8l6v679q5j2f7q8lpmcjr4mm3k@group.calendar.google.com';
var googleCalendarSync = mobiscroll.googleCalendarSync;
var currentView = 'agenda';
var firstDay;
var lastDay;
var loader;

function showLoader() {
  loader = loader || document.getElementById('demo-google-cal-loader');
  if (loader) {
    loader.style.visibility = 'visible';
  }
}

function hideLoader() {
  if (loader) {
    loader.style.visibility = 'hidden';
  }
}

function loadEvents() {
  showLoader();
  googleCalendarSync
    .getEvents(CALENDAR_ID, firstDay, lastDay)
    .then(function (resp) {
      hideLoader();
      calendar.setEvents(resp);
    })
    .catch(onError);
}

function onError(resp) {
  mobiscroll.toast({
    message: resp.error ? resp.error : resp.result.error.message,
  });
}

var calendar = mobiscroll.eventcalendar('#demo-google-cal', {
  view: {
    calendar: { type: 'week' },
    agenda: { type: 'week' },
  },
  exclusiveEndDates: true,
  onPageLoading: function (args) {
    var start = args.viewStart;
    var end = args.viewEnd;

    // Calculate dates
    // (pre-load events for previous and next pages as well)
    if (currentView === 'month') {
      firstDay = start;
      lastDay = end;
    } else {
      firstDay = new Date(start.getFullYear(), start.getMonth(), start.getDate() - 7);
      lastDay = new Date(end.getFullYear(), end.getMonth(), end.getDate() + 7);
    }

    loadEvents();
  },
  renderHeader: function () {
    return (
      '<div mbsc-calendar-nav class="mds-google-cal-nav"></div>' +
      '<div id="demo-google-cal-loader" class="mds-loader"></div>' +
      '<div class="mds-google-cal-switch mbsc-flex-1-0">' +
      '<label>Month<input mbsc-segmented type="radio" name="view" value="month" class="mds-google-cal-view"></label>' +
      '<label>Week<input mbsc-segmented type="radio" name="view" value="week" class="mds-google-cal-view"></label>' +
      '<label>Day<input mbsc-segmented type="radio" name="view" value="day" class="mds-google-cal-view"></label>' +
      '<label>Agenda<input mbsc-segmented type="radio" name="view" value="agenda" class="mds-google-cal-view" checked></label>' +
      '</div>' +
      '<div mbsc-calendar-prev class="mds-google-cal-prev"></div>' +
      '<div mbsc-calendar-today class="mds-google-cal-today"></div>' +
      '<div mbsc-calendar-next class="mds-google-cal-next"></div>'
    );
  },
});

document.querySelectorAll('.mds-google-cal-view').forEach(function (elm) {
  elm.addEventListener('change', function (ev) {
    currentView = ev.target.value;
    switch (currentView) {
      case 'month':
        calendar.setOptions({
          view: { calendar: { labels: true } },
        });
        break;
      case 'week':
        calendar.setOptions({
          view: { scheduler: { type: 'week' } },
        });
        break;
      case 'day':
        calendar.setOptions({
          view: { scheduler: { type: 'day' } },
        });
        break;
      case 'agenda':
        calendar.setOptions({
          view: {
            calendar: { type: 'week' },
            agenda: { type: 'week' },
          },
        });
        break;
    }
  });
});

googleCalendarSync.init({
  apiKey: '<YOUR_GOOGLE_API_KEY>',
  onInit: loadEvents,
});
```

### HTML

```html
<div id="demo-google-cal"></div>
```

### CSS

```css
.mds-google-cal-switch .mbsc-segmented {
  max-width: 300px;
  margin: 0 auto;
}

.mds-google-cal-nav {
  width: 200px;
}

.mds-loader {
  width: 32px;
  height: 32px;
  border: 4px solid #8c8c8c;
  border-bottom-color: transparent;
  border-radius: 50%;
  display: inline-block;
  box-sizing: border-box;
  animation: mds-loader-rotation 1s linear infinite;
  visibility: hidden;
}

@keyframes mds-loader-rotation {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* Material header order */

.mbsc-material.mds-google-cal-prev {
  order: 1;
}

.mbsc-material.mds-google-cal-next {
  order: 2;
}

.mbsc-material.mds-google-cal-nav {
  order: 3;
}

.mbsc-material .mds-google-cal-switch {
  order: 4;
}

.mbsc-material .mds-google-cal-today {
  order: 5;
}

/* Windows header order */

.mbsc-windows.mds-google-cal-nav {
  order: 1;
}

.mbsc-windows.mds-google-cal-prev {
  order: 2;
}

.mbsc-windows.mds-google-cal-next {
  order: 3;
}

.mbsc-windows .mds-google-cal-switch {
  order: 4;
}

.mbsc-windows .mds-google-cal-today {
  order: 5;
}
```

## Implementation notes

- Install the `@mobiscroll/calendar-integration` package. Call `googleCalendarSync.init({ apiKey: '<YOUR_GOOGLE_API_KEY>', onInit: loadEvents })` on mount to authenticate. Provide a `CALENDAR_ID` (the public Google Calendar ID).
- Set `exclusiveEndDates: true` on the Eventcalendar - Google Calendar uses exclusive end dates.
- Start with `view: { calendar: { type: 'week' }, agenda: { type: 'week' } }`. The view is switchable via a `SegmentedGroup` (Month / Week / Day / Agenda) in the custom header. On segment change, update the view: month → `{ calendar: { type: 'month' } }`, week → `{ scheduler: { type: 'week' } }`, day → `{ scheduler: { type: 'day' } }`, agenda → `{ calendar: { type: 'week' }, agenda: { type: 'week' } }`.
- Use `onPageLoading` to load events on every page change. Extract `args.viewStart` and `args.viewEnd` to determine the range. For non-month views, extend the range ±7 days to pre-load the previous and next pages. Call `googleCalendarSync.getEvents(CALENDAR_ID, firstDay, lastDay)` - it returns a Promise. On resolve, update the events array; on reject, show a Toast with the error message from `resp.error` or `resp.result.error.message`.
- Build a custom header using `renderHeader` (Angular: `headerTemplate`, Vue: `header` slot) containing: `CalendarNav`, a CSS loading spinner (toggle visibility while the Promise is pending), a `SegmentedGroup` for view switching, `CalendarPrev`, `CalendarToday`, `CalendarNext`.

## Run it in your project

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/javascript/getting-started/installation

## Related demos

- Previous: [Outlook Calendar Sync](https://demo.mobiscroll.com/javascript/agenda/sync-events-outlook-calendar.md) - Use the Javascript event calendar integration plugin to authenticate users, load their Outlook calendars, and display events in an agenda view.
