Skip to content
Go to app

Button and ks:subscribe

Open in ChatGPT

The button is the easiest way to turn visitors of your website into subscribers. It needs no API key, only the calendar id.

<div class="ks-subscribe" data-calendar="cal_XXXXXXXXXXXX"></div>
<script src="https://app.kalender-sync.de/embed/v1/button.js" async></script>
Live preview
Loading the button…
Snippet for your website

Replace cal_XXXXXXXXXXXX with the id of your calendar. Open the demo subscribe page

AttributeEffectDefault
data-calendarCalendar id (cal_ plus 12 characters). Required; without a valid id nothing renders.
data-colorHex color #rrggbb. The button picks the text color itself for enough contrast.#2563eb
data-labelCustom button text“Subscribe to calendar” / “Kalender abonnieren”
data-langde or enThe page’s lang, then the browser language, otherwise English

You need the script once per page. It renders every element with the class ks-subscribe and a data-calendar.

  • It renders into a shadow DOM. Your page’s CSS does not reach in, and its CSS does not leak out.
  • It sets no cookies, stores nothing and loads nothing besides the script itself.
  • The menu entries are plain links to https://app.kalender-sync.de/api/public/subscribe/{calendar_id}/go/{app}. Only that request creates the subscription and forwards to the calendar app. Your page sends no JavaScript requests to us, and you need no CORS.
  • Apps in the menu: Apple Calendar, Google Calendar, Microsoft 365, Outlook.com, Outlook (desktop) and “Other app”, which opens the subscribe page with the feed link. The app that fits the device comes first.
  • Escape closes the menu, so does a click outside.

We don’t track visitors. So that you still know how your button is used, it fires the ks:subscribe event on every click on a menu entry. It bubbles out of the shadow DOM (composed: true), so you can listen on the element or on document.

document.addEventListener('ks:subscribe', (event) => {
// event.detail = { calendar: 'cal_XXXXXXXXXXXX', app: 'google' }
const { calendar, app } = event.detail;
// Example: forward to your own analytics, under your consent
window.plausible?.('Calendar subscribe', { props: { calendar, app } });
});

app is one of: apple, google, office365, outlook, outlook_desktop, other.

The event runs entirely on your page. Whether and how you use it is up to you, and so is the consent for it.

Page builders (Elementor, Divi …) and single-page apps (React, Vue …) often insert content after the script ran. Then call this after inserting:

window.KalenderSync?.mountButtons();

Buttons that are already rendered stay unchanged. To re-render a button with other attributes, replace the element with a new one and call mountButtons() again.

Example for React:

useEffect(() => {
window.KalenderSync?.mountButtons();
}, []);
return <div className="ks-subscribe" data-calendar="cal_XXXXXXXXXXXX" />;

If you don’t want to embed a script, link the calendar’s subscribe_page_url with a button of your own. Subscriptions through the subscribe page are counted the same way.

The subscribe_links from the calendar response work too, but they are not counted in the statistics.

If your website sets a CSP, add to your existing directives:

script-src https://app.kalender-sync.de;
style-src 'unsafe-inline';
img-src data:;

You only need style-src and img-src if your CSP restricts those directives at all: the button brings inline styles in its shadow DOM, and the Microsoft icon is embedded as a data: image. connect-src and frame-src are not needed.