How To Embed React into a website

Embedded technologies are rising and the level of customization consumer desires grows with it. React can help us satisfy our consumers and our developers at the same time.

How To Embed React into a website

We all know the standard way to embed using iframe and it is nice and convenient until it's not.

When I think about embedding a product into a consumer web application, I think about 2 different consumers.

The first consumer is not a developer and he wants to customize his widget using some user interface at the provider application.

The second consumer is a developer who wants to dynamically customize the widget without ever going to the provider application.

To help the first consumer we can build a UI that represents all possible configurations, and then store this configuration in DB to load later when the consumer uses the widget with an associated identifier.

To help the developer, we need to allow the developer to pass data to our embedded widget dynamically and this is what I cover in this post.

Let's start with a demo first, embedded react widgets without any iframe.
Simple historic price of 2 coins since the beginning of the year.



Those embedded widgets are basically 2 instances of the same react application that run different configurations passed by the consumer.

In every react application the story starts with index.tsx (or js variant)
We get our root element and react renders the rest.

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
    <App />

When we talk about embedding, we talk about how we can have elements on the consumer page that we manage and the ability for the consumer to customize.

The consumer can also have multiple widgets embedded on the same page and therefore we can adjust our index.tsx to support rendering more than 1 element

The consumer will tag an HTML element with an identifier in this case a class name representing a certain type of widget.

<div class="ray_widget"></div>

We look up this identifier and render our widget.
We can also pass the whole HTML element as a prop to get all attributes the consumer has set for customization and control

const WidgetDivs = document.querySelectorAll('.ray_widget')

WidgetDivs.forEach(divElement => {
  const root = ReactDOM.createRoot(divElement);
      <Widget divElement={divElement}  />

Using HTML element as Prop

type Props = {
  divElement: Element

We then can use all the attributes as API and define an interface or a type to map all available options moreover, this can be used as documentation at later stages when you want to expose this to the consumer.

type WidgetAttributes = {
  "data-crypto": string
  "data-title": string
  "access_token": string
  "data-color": string,
  "data-background": string


Inside our widget component, we can then extract all the attributes and their values to render the widget on the consumer page according to their configurations.

const normalizeAttrs = (attr: WidgetAttributes) => {
  const { 
    "access_token": apiKey,
    "data-title": title,
    "data-crypto": crypto,
    "data-color": color,
    'data-background': background } = attr

  return {
    apiKey, title, crypto, color, background

const attr = Object.fromEntries(
      .map(item => [, item.value])
      ) as WidgetAttributes

  const { apiKey, title, crypto, color, background } = normalizeAttrs(attr)
attributes extraction for the HTML element

Final HTML element

      <div class="ray_widget"
 		data-title="Bitcoin Trend Widget"

This is basically the beginning of the embedded react widgets solution and from there imagination is the limit.

The final step is to bundle your application and the consumer needs to include the script on their website

<script src="https://your-react-app-bundle-cdn/index.js" type="text/javascript"></script>

I would also want to suggest thinking about the consumer target audience and their network capabilities as react might be over 300KB   and you might want to use the same technique with a different library like Svelete that weights less than 20KB.

Good luck on your journey :)