Skip to main content

Use the MetaMask onboarding library

Sending users away from your dapp to install MetaMask presents challenges. You must inform the user to return to your dapp and refresh their browser after the installation. Your dapp detects the user's newly installed MetaMask extension only after that refresh.

You can use MetaMask's onboarding library to improve and simplify the onboarding experience. The library exposes an API to initiate the onboarding process.

During the onboarding process, the library registers your dapp as the origin of the onboarding request. MetaMask checks for this origin after the user completes the onboarding flow. If it finds an origin, the final confirmation button of the MetaMask onboarding flow indicates that the user will be redirected back to your dapp.

tip

MetaMask SDK incorporates the functionality of the MetaMask onboarding library. You don't need to set up the onboarding library if you use the SDK.

Steps

  1. Install @metamask/onboarding.

  2. Import the library or include it in your page:

    // As an ES6 module
    import MetaMaskOnboarding from "@metamask/onboarding"
    // Or as an ES5 module
    const MetaMaskOnboarding = require("@metamask/onboarding")

    Alternatively, you can include the prebuilt ES5 bundle that ships with the library:

    <script src="./metamask-onboarding.bundle.js"></script>
  3. Create a new instance of the onboarding library:

    const onboarding = new MetaMaskOnboarding()
  4. Start the onboarding process in response to a user event (for example, a button click):

    onboarding.startOnboarding()

Example

The following are example ways to use the onboarding library in various frameworks:

import MetaMaskOnboarding from "@metamask/onboarding"
import React from "react"

const ONBOARD_TEXT = "Click here to install MetaMask!"
const CONNECT_TEXT = "Connect"
const CONNECTED_TEXT = "Connected"

export function OnboardingButton() {
const [buttonText, setButtonText] = React.useState(ONBOARD_TEXT)
const [isDisabled, setDisabled] = React.useState(false)
const [accounts, setAccounts] = React.useState([])
const onboarding = React.useRef()

React.useEffect(() => {
if (!onboarding.current) {
onboarding.current = new MetaMaskOnboarding()
}
}, [])

React.useEffect(() => {
if (MetaMaskOnboarding.isMetaMaskInstalled()) {
if (accounts.length > 0) {
setButtonText(CONNECTED_TEXT)
setDisabled(true)
onboarding.current.stopOnboarding()
} else {
setButtonText(CONNECT_TEXT)
setDisabled(false)
}
}
}, [accounts])

React.useEffect(() => {
function handleNewAccounts(newAccounts) {
setAccounts(newAccounts)
}
if (MetaMaskOnboarding.isMetaMaskInstalled()) {
provider // Or window.ethereum if you don't support EIP-6963.
.request({ method: "eth_requestAccounts" })
.then(handleNewAccounts)
provider // Or window.ethereum if you don't support EIP-6963.
.on("accountsChanged", handleNewAccounts)
return () => {
provider // Or window.ethereum if you don't support EIP-6963.
.removeListener("accountsChanged", handleNewAccounts)
}
}
}, [])

const onClick = () => {
if (MetaMaskOnboarding.isMetaMaskInstalled()) {
provider // Or window.ethereum if you don't support EIP-6963.
.request({ method: "eth_requestAccounts" })
.then((newAccounts) => setAccounts(newAccounts))
} else {
onboarding.current.startOnboarding()
}
}
return (
<button disabled={isDisabled} onClick={onClick}>
{buttonText}
</button>
)
}