For the complete documentation index, see llms.txt. This page is also available as Markdown.

Embedding graphs

Put a graph you built in the dashboard into your web or mobile app.

Every embed needs the same two things: the graph id from Dashboard → Graphs (select Embed on a card to copy it) and the Terra user id of the person looking at it.

Use example in place of a user id to render generated data while you build.


Web

On the web, graphs render directly into your page. There's no iframe, so the chart sizes to its container, inherits your layout, and behaves like any other element.

npm install @tryterra/graphs-react
import { TerraGraph } from "@tryterra/graphs-react";

export function StepsCard({ terraUserId }) {
  return (
    <TerraGraph
      sessionId="YOUR_GRAPH_ID"
      userId={terraUserId}
      timeframe={30}
      style={{ width: "100%", height: 360 }}
      onError={(error) => console.error(error.message, error.traceId)}
    />
  );
}

Works in Next.js, Remix and Astro with no dynamic() wrapper — the component renders nothing on the server and mounts in the browser.

npm install @tryterra/graphs
<script type="module">
  import "@tryterra/graphs";
</script>

<terra-graph
  session-id="YOUR_GRAPH_ID"
  user-id="TERRA_USER_ID"
  timeframe="30"
></terra-graph>

<style>
  terra-graph { display: block; width: 100%; height: 360px; }
</style>

Tell the Vue compiler that terra-graph is a custom element, in vite.config.js:

The element has no height of its own — give it one, or it collapses.

The chart engine is loaded from Terra when a graph mounts, which is what keeps every embed in step with the dashboard. If you run a Content Security Policy, allow script-src https://api.tryterra.co, connect-src https://api.tryterra.co, and — to keep Terra's typeface — font-src https://fonts.gstatic.com and style-src https://fonts.googleapis.com.


React Native

React Native has a package of its own, which draws the graph as native views — no web view:

There is no chart engine to install or configure — the package ships its own. The one thing it can't bundle is a drawing surface, since React Native has none built in: react-native-svg is a native module, declared as a peer so npm installs it for you.

On Expo, run npx expo install react-native-svg once afterwards so the version matches your SDK.

For faster painting on very dense charts, import @tryterra/graphs-react-native/skia instead and add @shopify/react-native-skia and react-native-reanimated. Same component, same props.

react-native-svg ships inside Expo Go, so this runs there as-is — no development build needed. If you would rather add no native modules at all, use the web view below.

One difference worth knowing. On the web, the chart engine is loaded from Terra at render time, so improvements reach your users as soon as we ship them. A native app bundles it instead, so it picks them up when you upgrade the package and release a new build. If you would rather never think about that, the web view below is the option that keeps it.


Other mobile platforms

iOS, Android and Flutter load the hosted graph in a web view. React Native can too, with react-native-webview, if you would rather not add a charting library:

The same URL works in an <iframe> on the web, if you'd rather not add a package.


Choosing the date range

Every embed takes the same three settings — as props in React, attributes in HTML, and query parameters in a URL.

Setting
Renders

timeframe = 30

The most recent 30 days, including today.

from = 2026-08-01, to = 2026-08-31

1–31 August, with to included.

timeframe = 7, from = 2026-08-01

Seven days starting 1 August.

timeframe = 7, to = 2026-08-31

The seven days ending 31 August.

from = 2026-08-01

1 August through today.

Dates are YYYY-MM-DD in UTC. A range can cover at most 92 days. With nothing set, you get the last 7 days.

Changing the range redraws the chart in place rather than reloading it, so you can wire a date picker straight to it:

A graph set to Single session scope ignores the range and always shows the user's latest workout, night or day.


Matching your app's theme

A graph's colours are part of its design in the dashboard, so the usual answer is to set them there — every embed picks the change up without a release on your side.

For colours that have to follow the app at runtime, such as a dark-mode toggle, pass a theme:

It's a theme property on the element too, if you aren't using React:

Give colours as hex or rgb(). If you need two colour schemes of the same chart, building two graphs in the dashboard is usually simpler than theming at runtime.


When a graph doesn't render

A graph that can't be drawn says so in place, and reports a trace id. Quote that id to Terra support and we can see exactly what happened.

On the element it's a terra-graph:error event carrying the same thing, plus a data-state attribute (loading, ready or error) and data-trace-id on failure.

The common causes:

What you see
Usually means

No data found for this time period

Terra holds no data for that user over that range. Check the user in Dashboard → Users, and widen the range.

Invalid graph session ID

The graph id is wrong, or the graph was deleted. Copy it again from Embed.

Invalid graph type requested

The graph was created against an old graph type. Open it in the editor and re-pick the metric.

Nothing renders, no error

The element has no height. Give it one in CSS.

A blocked request in the console

A Content Security Policy is blocking api.tryterra.co — see the note above.


Changing a graph after you've shipped

Graph ids are stable. Edit a graph in the dashboard — different metric, different colours, an extra header stat — and every embed of it changes on the next load. You don't need to touch your app.

Deleting a graph stops it rendering everywhere it's embedded, so check Viewers first if you're not sure who's using it.

Last updated

Was this helpful?