Docs · Embed

Embed a chart that stays alive

One hosted script, one custom element, no build step. The chart draws itself in, morphs when its spec changes, and carries its own accessibility — this page is the full contract. For the two-minute version, start at get started.


1 · Load the element

The bundle is self-contained — engine included, about 30 KB gzipped — and served from this domain with CORS open, so the same tag works on any origin. Hover, tooltips and keyboard navigation arrive in a small second file right after the chart paints (/v1/live-chart-interact.js), and a live table loads one more on demand (/v1/live-chart-table.js), only on pages that actually show a table.

<script type="module" src="https://meikucharts.com/v1/live-chart.js"></script>

2 · Drop a chart with its spec as a JSON child

The way most embedders start: the spec travels inside the element, so the snippet is one self-sufficient block of HTML.

<live-chart>
  <script type="application/json">
    {
      "type": "column",
      "theme": "editorial",
      "title": "Weekly Signups",
      "source": "Product analytics",
      "data": {
        "labels": [
          "Mon",
          "Tue",
          "Wed",
          "Thu",
          "Fri"
        ],
        "series": [
          {
            "name": "Signups",
            "values": [
              12,
              19,
              14,
              27,
              22
            ]
          }
        ]
      }
    }
  </script>
</live-chart>

3 · Or pass the spec another way

Three inputs, same result — pick whichever fits the page. A spec attribute carrying JSON suits server-rendered templates:

<live-chart spec='{"type":"line","theme":"mint","data":{"labels":["Q1","Q2","Q3"],"series":[{"values":[12,19,27]}]}}'></live-chart>

And the spec property suits scripts — assign a plain object, no serialization. Setting it on a mounted chart is also how you morph:

const chart = document.querySelector("live-chart");
chart.spec = {
  "type": "line",
  "theme": "mint",
  "title": "Weekly Signups",
  "source": "Product analytics",
  "data": {
    "labels": [
      "Mon",
      "Tue",
      "Wed",
      "Thu",
      "Fri"
    ],
    "series": [
      {
        "name": "Signups",
        "values": [
          18,
          24,
          20,
          33,
          29
        ]
      }
    ]
  }
};

The element re-parses on every change and the engine animates from the old shape to the new one — including across chart types. There is no separate update API to learn.


Sizing

The host renders as a block, full width, 300 px tall by default. Size it like any element — the canvas follows its box, crisp on high-DPI screens:

live-chart {
  height: 420px;      /* default is 300px */
  max-width: 720px;
}

On third-party pages the chart carries a small "Made with Meiku Charts" line under the canvas — that credit is how the free hosted bundle pays for itself. It is a nofollow link (Google's own rule for widget links), takes ~16 px, and never appears on meikucharts.com or on localhost while you develop.


Pro and the embed credit

With Pro, every chart on the websites in your account loses the credit. Nothing to change in your pages. Optional: add license="mk_…" with your site key so a new chart starts clean on its very first view. Never put the Pro key in page code. When your Pro has websites, makers in a browser with Pro enabled include the site key in copied embed code. Pro covers one website, including its subdomains; Team covers up to 10. Both use your own credit line or no credit.

If your site sets a Content-Security-Policy, add https://lic.meikucharts.com to connect-src (and https://meikucharts.com if you use the optional license attribute). Without them, charts keep the credit and nothing breaks. During a network outage, a previous successful check keeps the credit-free chart for up to 7 days in that visitor’s browser; a new visitor sees the credit. Attempts to hide the Free credit restore it and add a meikucharts.com mark inside the chart. Follow How to turn on Pro for setup.

States you can style and script against

The host mirrors the engine's state as an attribute: "animating" while drawing or morphing, "idle" once settled. Our tests wait for state="idle"; a host page can do the same, or hook CSS on it:

live-chart[state="animating"] { /* drawing or morphing */ }
live-chart[state="idle"]      { /* settled */ }

A spec that fails to parse never throws: the chart shows a short structured message, and the element's error property returns the same {path, message, hint} list the spec reference documents.


Accessibility, built in

Every chart ships a hidden data table with its raw values (screen readers get the truth, not a description of pixels), an aria-label naming the chart, and keyboard navigation — Tab to the canvas, arrows between marks, Escape out — with a visible focus ring. Hover tooltips have keyboard parity. None of this needs configuration.


Theming the embed

Charts and tables follow their theme's light or dark variant. Pass options.variant as "auto" and the embed follows your page: its own dark-mode toggle first — a data-theme (or data-bs-theme) attribute or a dark class on html/body, or a color-scheme — then the visitor's OS preference, and it switches live when the toggle flips. Omitting the variant shows the theme's own canonical side; pinning "light"/"dark" keeps one side whatever the page does. A live table dropped into an article can also take the page's own font (options.font: "inherit"), a lid (options.height), a search box (options.search) and pages (options.pageSize). Details and the format/target options live in the spec reference.


What the embed never does

Chart data renders in the visitor’s browser. Embeds set no cookies and do not track viewers. The element loads its scripts and asks lic.meikucharts.com whether the website has Pro, sending only the website’s name. When the website has no site pass, an embed with the optional license attribute also sends the public site key and page hostname to meikucharts.com for a license check, normally once a day. Neither check sends chart data, page contents or visitor cookies. See the Privacy policy.