Skip to content
C MakeCalendarLink

The embed widget

One button that opens a calendar picker. Two lines of HTML, no dependencies, no cookies, and it cannot be broken by your site's CSS.

Live example

That button is the widget, running on this page with the snippet below.

The snippet

<div data-add-to-calendar
     data-title="Q4 product webinar"
     data-start="2026-12-10T14:00"
     data-end="2026-12-10T15:00"
     data-timezone="Europe/Brussels"
     data-location="https://meet.example.com/abc-defg-hij"></div>

<script src="https://makecalendarlink.com/embed.js" async defer></script>

Load the script once per page, however many buttons you have. The generator will fill this in for you if you would rather not type dates by hand.

Attributes

AttributeRequiredNotes
data-title yes Event title.
data-start yes 2026-09-10T14:00, or 2026-09-10 for all-day.
data-end no Defaults to the start value.
data-timezone no IANA zone. Defaults to the visitor's own zone, which is usually not what you want, so set it.
data-all-day no true for an all-day event.
data-location no Address or meeting URL.
data-description no Event description.
data-url no Event page, appended to the description.
data-rrule no Recurrence, e.g. FREQ=WEEKLY;COUNT=8.
data-reminder no Minutes before start, .ics only.
data-label no Button text. Defaults to "Add to calendar".
data-providers no Comma separated subset of google,outlook,office365,yahoo,ics.
data-track no on routes clicks through this site so they can be counted.

Styling

Set these custom properties on the element to match your design:

[data-add-to-calendar] {
  --atc-bg: #111827;
  --atc-bg-hover: #1f2937;
  --atc-color: #ffffff;
  --atc-border: #111827;
  --atc-radius: 999px;
  --atc-padding: 12px 20px;
  --atc-font-size: 15px;
  --atc-accent: #6366f1;
}

The widget also respects prefers-color-scheme, so it stays readable on a dark site without any configuration.

Accessibility

The trigger is a real button with aria-expanded, the menu has role="menu", arrow keys move between items and Escape closes and returns focus. It works without a mouse.

Single page apps

A MutationObserver picks up widgets added after load, so most frameworks need nothing extra. If you render into a detached tree and attach it later, call window.addToCalendar.scan() once afterwards.

Widget questions

How big is the script? +
A few kilobytes gzipped, with no dependencies. Load it async and it will not affect your Core Web Vitals.
Will it clash with my site CSS? +
No. The widget renders inside a shadow root, so your styles cannot leak in and its styles cannot leak out. Use the CSS custom properties to restyle it deliberately.
Does it work in React, Vue or Svelte? +
Yes. Render the div as usual and load the script once. The widget watches the DOM, so components mounted later are picked up automatically. You can also call window.addToCalendar.scan() after a render.
Can I use it in an email? +
No. Email clients strip JavaScript. Use the plain HTML snippet from the generator instead.
Can I self-host the script? +
Yes. Download it, drop it in your assets and point the src at your own copy. Nothing calls home unless you turn on click counting. Source.