How to integrate Maqpie widget into React application.

Widget

Hey everyone! Looks like you’re interested in integration Maqpie chat into your product. Setup wizard in our admin portal helps to install chat quick and easy in many cases but we also get questions about integration with Single Page Applications. This article should make it clear. We chose React as a framework for this guide.

Setup Wizard

Let’s start with loading and initializing the widget. Basically below is the snippet from the setup wizard, just wrapped into the react component. Here we define user data and chat settings and make some magic that lets us call methods of public api of chat immediately even if the widget isn’t loaded yet.

maqpie.js

import React from 'react';

const METHODS = [
  'renderLargeView',
  'showLargeView',
  'destroyLargeView',
  'subscribe',
  'unsubscribe',
];

export default function MaqpieWidget({ appId, user, userHash, headerColor, scrollColor }) {
  React.useEffect(() => {
    if (appId && user) {
      window.MP = { // you can find all fields in setup wizard in admin portal
        data: {
          appId,
          user,
          userHash,
        },
        settings: {
          styles: {
            headerColor, // a primary chat color
            scrollColor, // a color of the chat scroll
          },
        },
      };

      window.MP._queue = window.MP._queue || [];
      METHODS.forEach((method) => {
        window.MP[method] = (...args) => {
          const data = [method, ...args];
          window.MP._queue.push(data);
        };
      });

      let script = document.querySelector('script[src="https://widget.maqpie.com/widget/v1.0"]');
      if (script) {
        return;
      }

      script = document.createElement('script');
      script.type = 'text/javascript';
      script.async = true;
      script.src = 'https://widget.maqpie.com/widget/v1.0';
      document.body.append(script);
    }
  }, [appId, user, userHash, headerColor, scrollColor]);

  return null;
}

Then we use our sweet component somewhere in application. We recommend to use it as close to root component as possible to avoid unnecessary renderings.

App.js

<Maqpie
  appId="your_app_id"
  user={{
    username: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    email: 'john@demo.com',
    userId: 'testUser1',
  }}
/>

That’s it! Pretty straightforward, isn’t it?

But what if a small widget is not enough and you want to embed chat that should fit the size of the page?

Embedded mode

Embedded chat

Let’s change a bit our wrapper component.

maqpie.js

export default function MaqpieWidget({ appId, user, userHash, headerColor, scrollColor, embedded }) {
  React.useEffect(() => {
    if (appId && user) {
      window.MP = { // you can find all fields in setup wizard in admin portal
        data: {
          appId,
          user,
          userHash,
        },
        settings: {
          styles: {
            headerColor, // a primary chat color
            scrollColor, // a color of the chat scroll
          },
          // here we say Maqpie to be embedded
          mode: embedded ? 'embedded' : undefined,
        },
      };

      window.MP._queue = window.MP._queue || [];
      METHODS.forEach((method) => {
        window.MP[method] = (...args) => {
          const data = [method, ...args];
          window.MP._queue.push(data);
        };
      });

      let script = document.querySelector('script[src="https://widget.maqpie.com/widget/v1.0"]');
      if (script) {
        return;
      }

      script = document.createElement('script');
      script.type = 'text/javascript';
      script.async = true;
      script.src = 'https://widget.maqpie.com/widget/v1.0';
      document.body.append(script);
      
      // initialize embedded chat
      if (embedded) {
        window.MP.renderLargeView('maqpie-chat');
        window.MP.showLargeView();

        // clean up resources when user leave page (component umnount)
        return () => {
          window.MP.destroyLargeView();
        };
      }
    }
  }, [appId, user, userHash, headerColor, scrollColor, embedded]);

  // and add root component for our chat
  return (
    <div id="maqpie-chat">
    </div>
  );
}

And of course update the parent component.

App.js

<Maqpie
  appId="your_app_id"
  user={{
    username: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    email: 'john@demo.com',
    userId: 'testUser1',
  }}
  embedded
/>

Cool! Can I add a badge with number of unread messages to menu?

Sure! You can subscribe to unreadMessagesCountChanged event and keep your site in sync with Maqpie. I'll use React's state for this example but you can do it with your favourite state management tool like Redux or Mobx. The trick here is that we need to subscribe after we initialize our chat. So, let's do one more change to our maqpie.js file.

maqpie.js

export default function MaqpieWidget({ appId, user, userHash, headerColor, scrollColor, embedded, onMessageCountChange }) {
  React.useEffect(() => {
    if (appId && user) {
      window.MP = { // you can find all fields in setup wizard in admin portal
        data: {
          appId,
          user,
          userHash,
        },
        settings: {
          styles: {
            headerColor, // a primary chat color
            scrollColor, // a color of the chat scroll
          },
          // here we say Maqpie to be embedded
          mode: embedded ? 'embedded' : undefined,
        },
      };

      window.MP._queue = window.MP._queue || [];
      METHODS.forEach((method) => {
        window.MP[method] = (...args) => {
          const data = [method, ...args];
          window.MP._queue.push(data);
        };
      });

      let script = document.querySelector('script[src="https://widget.maqpie.com/widget/v1.0"]');
      if (script) {
        return;
      }

      script = document.createElement('script');
      script.type = 'text/javascript';
      script.async = true;
      script.src = 'https://widget.maqpie.com/widget/v1.0';
      document.body.append(script);

      // subscribe to unread messages count
      if (onMessageCountChange) {
        window.MP.subscribe('unreadMessagesCountChanged', onMessageCountChange);
      }
      
      // initialize embedded chat
      if (embedded) {
        window.MP.renderLargeView('maqpie-chat');
        window.MP.showLargeView();
      }
    }
  }, [appId, user, userHash, headerColor, scrollColor, embedded, onMessageCountChange]);

  // and add root component for our chat
  return (
    <div id="maqpie-chat">
    </div>
  );
}

We've added onMessageCountChange property. It must be a function that accepts single parameter - current number of unread messages.  You might noticed that clean up code disappeared. I moved this part to App.js file to make it work correctly because when we update state, React recreates children of this component and executes our clean up code. But don't worry, we won't reload the chat :) Let's have a look at the result.

App.js

function App() {
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    // clean up resources when user leave page (component umnount)
    return () => {
      window.MP.unsubscribe();
      window.MP.destroyLargeView();
    };
  });

  return (
    <div className="App">
      <div>Unread messages count: {count}</div>
      <Maqpie
        appId="your_app_id"
        user={{
          username: 'John Doe',
          firstName: 'John',
          lastName: 'Doe',
          email: 'john@demo.com',
          userId: 'testUser1',
        }}
        onMessageCountChange={setCount}
      />
    </div>
  );
}

Conclusion

So, we just added a fully functional chat into your application and it took about 10 minutes instead of months of development and testing. Nice performance :)

You can find the code of this example in our Github. Hope you find this article helpful and become our next big customer!