How to Receive Data From an iframe

In this blog post we explore how to receive data from an iframe.

hero banner

In this blog post we are going to explore how to receive data from an iframe. We are seeing technical trends begin to push Web Based Development towards Progressive Web Applications and Single Page Applications. Responsive applications are becoming an expectation for many end users in the age of mobile devices.

Keeping a user on your application while gathering data from various sources can be a challenge with the growing amount of SaaS integrations. Integrating these tools while creating a seamless white labeled experience can be challenging.

In this blog we go over how to receive data from an iframe to the parent page.

What’s the problem?

If you’ve built an app using a SaaS or CSaaS tool, then you’ve dealt with Redirect URI’s to send your user back to your application after they leaving the third-party page. But what if your user never had to leave your application to utilize these tools.

Let’s explore this question further in the coming sections!

Requirements

Let’s use the Nylas Scheduler to show how we can iframe an integration to send a message from the iframe to the parent page. The iframe will communicate back that the user booked a meeting while persisting all data from the scheduled meeting. To learn more about the Nylas Scheduler, check out our blog post on How to Create a Scheduler Calendar.

Receive Data with iframe

To start, we initiate our application and embed the Nylas Scheduler in an iframe on the page. For this example, I will be using a React Application. These principles for receiving data with iframe are possible with any front-end technology including vanilla JavaScript.

Starting our Project

First, we will create the template application:

import './App.css';

function App() {
  return (
    <Router>
      <div className="App">
        <h2 className='App-header'>IFrame Scheduler Demo</h2>
      </div>
    </Router>
  );
}

export default App;

This is a boiler plate template from create-react-app with some of the unneeded code and imports removed.

Creating a iframe Component

Now, we create an iframe component to use on our desired route:

export default function Iframe({iframesrc}) {
    return <iframe src={iframesrc} title="Iframe Scheduler" width="100%" height="1000"></iframe>;
}

We are passing through a prop here as the Nylas Scheduler supports multiple scheduling pages, and you may want to pass different pages based on who the end user is booking an appointment with.

Importing our Component

Now for our demo, we will import this into our main application and set up routing to make this iframe the default route using BrowserRouter from react-router-dom:

import './App.css';
import {
  BrowserRouter as Router,
  Routes,
  Route,
} from "react-router-dom";
import Iframe from './components/iframe';

function App() {

	const iframesrc = process.env.REACT_APP_IFRAME_URL

  return (
    <Router>
      <div className="App">
        <h2 className='App-header'>IFrame Scheduler Demo</h2>
        <Routes>
          <Route exact path="/" element={<Iframe iframesrc={iframesrc}/>}/>
        </Routes>
      </div>
    </Router>
  );
}


export default App;

In our example, we are retrieving the iframe URL from our environment variables, however in a production environment we would retrieve this from our backend based on who the user is trying to book with.

Handling the Redirect

Next let’s create a redirect page. This page will be where our Nylas Scheduler redirects to after a booking is complete and will be in charge of capturing the booking data and informing the parent page about the booking.

import { useEffect } from "react";
import { useSearchParams } from "react-router-dom";

export default function Redirect() {

    const [searchParams] = useSearchParams();

    useEffect(() => {
				/*
				Structure of my use cases data:
				{
					"start_time": 123123123,
					"end_time": 123123124,
					"name": "Chase"
				}
				*/
        const data = Object.fromEntries([...searchParams])

        if(data){
            window.parent.postMessage(data, 'http://localhost:3000/meetingdetails');
        }
    }, [searchParams]);

    return <p>You made it to the redirect</p>;
}

Now we’ve got a component that will capture the redirect from the Nylas Scheduler and then post a message from the iframe to the parent page persisting the data received as well! As an extra layer of security for our application, we are passing through the originating URL in the postMessage call.

Handling the Redirect from our iframe

Lets add a route for this redirect component and an event listener to our application to capture this message and data being posted to the parent page! We will do this in the main file for our app using the useEffect and useState hooks in React.

import './App.css';
import {
  BrowserRouter as Router,
  Routes,
  Route,
} from "react-router-dom";
import Redirect from './components/redirect';
import Iframe from './components/iframe';
import { useEffect, useState } from 'react';

function App() {

  const iframesrc = process.env.REACT_APP_IFRAME_URL

  const [data, setData] = useState({})

  function listener (e) {
    // Get the sent data
    const iframeData = e.data;

    if (iframeData.account_id){
      setData(iframeData)
      sessionStorage.setItem("renderData", JSON.stringify(iframeData))
    }

  }

  useEffect(() => {
    window.addEventListener('message', listener);

    return () => window.removeEventListener('message', listener)
  }, [setData])

  return (
    <Router>
      <div className="App">
        <h2 className='App-header'>IFrame Scheduler Demo</h2>
        <Routes>
          <Route exact path="/" element={<Iframe iframesrc={iframesrc}/>}/>
          <Route exact path="/redirect" element={<Redirect/>}/>
        </Routes>
      </div>
    </Router>
  );
}


export default App;

Now that we have a listener in place, we are capturing the event sent from the iframe to the parent page as well as the data included in that message!

Handling the data with iframe

Finally, let’s render this data so we can see what is being passed back in the message from the iframe to the parent:

import '../App.css'

export default function Meeting(props) {
    
    const renderData = JSON.parse(sessionStorage.getItem('renderData'))
    if(renderData.account_id) {
        console.log('Data has account ID')
      return Object.entries(renderData).map(([key, value], i) => {
        return (
          <div className='Scheduler-data'>
            <b>{key}: </b>
            <p>{value}</p>
          </div>
        )
      })
    } else {
      return(
        <div>
          <p>No Meeting Details</p>
        </div>
      )
    }
  }

In this component, we are creating a simple method for iterating over the data which is stored in the session storage.

Finishing things up in our app

Finally, we need to set up a method to render this component to display the data received:

import './App.css';
import {
  BrowserRouter as Router,
  Routes,
  Route,
} from "react-router-dom";
import Redirect from './components/redirect';
import Iframe from './components/iframe';
import Meeting from './components/postbooking';
import { useEffect, useState } from 'react';

function App() {

  const iframesrc = process.env.REACT_APP_IFRAME_URL

  const [data, setData] = useState({})

  function listener (e) {
    // Get the sent data
    const iframeData = e.data;

    if (iframeData.account_id){
      setData(iframeData)
      sessionStorage.setItem("renderData", JSON.stringify(iframeData))
    }

  }

  useEffect(() => {
    window.addEventListener('message', listener);

    return () => window.removeEventListener('message', listener)
  }, [setData])

  useEffect(() => {
    if(data.account_id) {
      window.location.assign('http://localhost:3000/meetingdetails')
    }
  }, [data])

  return (
    <Router>
      <div className="App">
        <h2 className='App-header'>IFrame Scheduler Demo</h2>
        <Routes>
          <Route exact path="/" element={<Iframe iframesrc={iframesrc}/>}/>
          <Route exact path="/redirect" element={<Redirect/>}/>
          <Route path="/meetingdetails" element={<Meeting/>}/>
        </Routes>
      </div>
    </Router>
  );
}


export default App;

We just created an application allowing us to redirect the user and receive data with iframe informing our application!

That’s a Wrap

Being able to receive data from an iframe to the parent page lets you create white labeled functionality with tools like the Nylas scheduler used in this demo. With all the tools we integrate into our applications, creating a consistent method to receive data with iframe is a powerful utility.

Continue building with Nylas and learn more by visiting the documentation. Sign up here if you need to create a Nylas account for free!

You May Also Like

Transactional Email APIs vs Contextual Email APIs
Best email tracker
Find the best email tracker and elevate your app’s email game
How to create and read Webhooks with PHP, Koyeb and Bruno

Subscribe for our updates

Please enter your email address and receive the latest updates.