Logo

Build Customer Dashboard

With the Consumer Portal, you can build in-app user-facing dashboards where your customers can follow their consumption in real-time. We provide the authentication layer and React hooks to fetch data from OpenMeter so you can focus on building your application.

Authentication

The Consumer Portal uses token authentication to grant access to your users to their usage. The token is generated on your backend via OpenMeter SDK or API and is valid for 24 hours or until you invalidate it. Every portal token belongs to one specific subject and can be limited to one or multiple meter(s) optionally.

Because a portal token belongs to a specific subject, you can use it in your frontend application to query usage; as long as you ensure tokens are not shared between users.

  • If you're using OpenMeter Cloud, you can directly call the portal meter query Cloud API in your web application.
  • If you're using OpenMeter open source, you'll need to expose the portal meter query endpoint (/api/v1/portal/meters/{meterSlug}/query) to your users.

How to generate a portal token

Portal tokens should be generated on your backend and passed to your frontend application. You can generate a portal token using the OpenMeter Cloud API or the OpenMeter SDK as the following:

import { OpenMeter } from '@openmeter/sdk';
 
const openmeter = new OpenMeter({
  baseUrl: 'https://openmeter.cloud',
  token: '<API_TOKEN>', // Cloud only
});
 
const token = await openmeter.portal.createToken({ subject: 'customer-1' });
// { token: 'om_portal_xxx', subject: 'customer-1', expiresAt: '2021-01-02T00:00:00.000Z' }

Caution: Never share your Secret API Key with your customers or frontend application. Only portal tokens should be shared with your users.

Query Usage with React

Once you have a portal token, you can query usage in your front-end application.

OpenMeter Provider

The OpenMeter Provider is a React Context Provider that will handle your authentication. We recommend setting up this provider at the root of your pages where you want to use OpenMeter React hooks.

A full example for Next.js can be found here.

Check out the following example that fetches a portal token from your backend and passes it to the OpenMeter Provider.

import React from 'react';
import ReactDOM from 'react-dom';
import { OpenMeterProvider } from '@openmeter/web/react';
 
const MyApp = () => {
  const [token, setToken] = React.useState(null);
 
  React.useEffect(() => {
    // Prerequisite: You'll need an endpoint that returns the Portal Token
    // This endpoint should be authenticated
    fetch(`/your-backend-service/openmeter/portal`, { method: 'POST' })
      .then((res) => res.json())
      .then(({ token }) => setToken(token));
  }, []);
 
  return (
    <OpenMeterProvider url="https://openmeter.cloud" token={token}>
      <div>
        <h1>My App</h1>
        <div>...</div>
      </div>
    </OpenMeterProvider>
  );
};
 
ReactDOM.render(<MyApp />, document.body);

Query Subject Usage

Once we have the OpenMeter Provider setup, we can use the useOpenMeter hook to get an OpenMeter client. Components using OpenMeter React hooks need to be a child component of the <OpenMeterProvider>.

import type { WindowSize } from '@openmeter/web';
import { useOpenMeter } from '@openmeter/web/react';
 
export default function UsageDashboard() {
  const openmeter = useOpenMeter();
 
  // We recommend to use react-query to handle the loading state, refetching, etc.
  const [data, setData] = useState<MeterQueryRow[] | null>(null);
  useEffect(() => {
    if (openmeter) {
      // Get daily usage for the `tokens` meter for 2023 October
      // You can set the period for the customer's billing cycle
      const query = async () => {
        const { data } = await openmeter.queryPortalMeter({
          meterSlug: 'tokens',
          windowSize: WindowSize.Day,
          from: new Date('2023-10-01T00:00:00Z'),
          to: new Date('2023-10-31T00:00:00Z'),
        });
        return data;
      };
 
      query()
        .then((data) => setData(data))
        .catch((err) => console.error(err));
    }
  }, [openmeter]);
 
  return (
    <table>
      <tr>
        <th>Period</th>
        <th>Usage</th>
      </tr>
      {data.map(({ value, windowStart, windowEnd }) => (
        <tr key={windowStart}>
          <td>
            {windowStart} - {windowEnd}
          </td>
          <td>{value}</td>
        </tr>
      ))}
    </table>
  );
}

Note how we didn't pass subject to the React Hook as this is already handled by the <OpenMeterProvider>.

Limiting Portal Access

Portal tokens are restricted to a single subject by design, but you can also restrict them to one or multiple meters. This is useful if you have multiple meters to track customer usage, but you don't want to give access to all of them to your users.

For example, you can restrict a portal token to the tokens meter as the following:

const token = await openmeter.portal.createToken({
  subject: 'customer-1'
  allowedMeters: ['tokens']
})