Put Dium on your site

Mount the full app under your own path, link to your Flow, or embed the member map.

Last updated

Pick the right option

Dium does not have a drop-in JavaScript widget. You have three real options.

OptionWhat members seeSign-inNeeds
Mount (recommended)The full Dium app under your own path, such as yoursite.com/learning/dium/Works, first-partyA server that runs PHP, and a partner key
Link outYour Flow on dium.ioWorks, with the token flowNothing, or a key for autologin
Member map iframeA map of Flow members who share a locationNot neededYour origin on our allowlist

How the mount works

The mount is a short PHP file from Dium that you place on your own server. When a member opens a page under your path, it:

  1. Reads the path and works out which Flow, Wave or Page to show.
  2. Writes a small config object, window.__DIUM, with Dium's API address, your basePath, your partnerId, a back link and an app name.
  3. Picks up a dium_token from the URL after autologin, stores it in localStorage and removes it from the address bar.
  4. Checks the session with auth.php validate using a Bearer header.
  5. Loads Dium's app script from https://dium.io/api/js/app.js.

Before it works, we register your key, allow your origin and add your host to the redirect allowlist. See how to get a key.

Install by platform

Works on any host that runs PHP, such as Apache or nginx with PHP-FPM.

  1. Copy the mount template we send you to a folder on your site, such as /learning/dium/index.php.
  2. Put dium_config.php outside the web root and fill in DIUM_PARTNER_ID, DIUM_PARTNER_KEY and DIUM_BASE_PATH.
  3. Route every path under the mount to index.php.
  4. Link to /learning/dium/ from your navigation.
File layout
your-site/
  learning/
    dium/
      index.php        <- copy of Dium's partner mount template
      .htaccess        <- sends every sub-path to index.php
private/
  dium_config.php      <- DIUM_PARTNER_ID, DIUM_PARTNER_KEY, DIUM_BASE_PATH (outside the web root)
Apache rewrite
# learning/dium/.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]

Theming

Each Flow has its own logo, banner, primary colour and accent colour, set by the Flow owner in settings. The mounted app uses them. There is no custom CSS hook or theme API for partners today.

The member map iframe

The member map shows Flow members who have a location on their Moat profile. It is the only Dium surface built to sit in an iframe. It sends a Content-Security-Policy: frame-ancestors header built from Dium's allowed origins, so it only renders on sites we have approved.

Iframe
<iframe
  src="MAP-URL-WE-SEND-YOU"
  title="Community member map"
  width="100%" height="480"
  loading="lazy"
  style="border:0;border-radius:16px"></iframe>

Sizing. The map does not resize itself. Give the iframe a fixed height, as above.

Security

  • No framing of the app. Dium's app pages send X-Frame-Options: DENY. That blocks clickjacking and is why the mount runs on your domain instead of in a frame.
  • Allowlists, not wildcards. Framing is controlled with CSP frame-ancestors listing exact origins. The old ALLOW-FROM option no longer works in browsers.
  • postMessage. Dium does not send or listen for postMessage today. If you add your own messaging to a frame, check event.origin with an exact match, never post to "*", and never put message data into innerHTML.
  • Keys stay on the server. dium_config.php holds your partner key. Keep it outside the web root.
Safe message handling
// Only if YOU add messaging between your page and a frame you control.
// Dium itself does not send postMessage events today.
const TRUSTED = "https://dium.io";

window.addEventListener("message", (event) => {
  if (event.origin !== TRUSTED) return;          // exact match, not includes()
  const msg = event.data;
  if (!msg || typeof msg.type !== "string") return;
  statusEl.textContent = String(msg.text ?? ""); // textContent, never innerHTML
});

frame.contentWindow.postMessage({ type: "hello" }, TRUSTED);   // never "*"