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
| Attribute | Required | Notes |
|---|---|---|
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? +
Will it clash with my site CSS? +
Does it work in React, Vue or Svelte? +
window.addToCalendar.scan() after a render.