Skip to content

Instantly share code, notes, and snippets.

@srestraj
Last active March 28, 2024 22:56
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save srestraj/eed9d2f199ac4024e029e3012ff2829b to your computer and use it in GitHub Desktop.
Save srestraj/eed9d2f199ac4024e029e3012ff2829b to your computer and use it in GitHub Desktop.
Integrate Google Sign-in with Nuxt 3.

Integrate Google Sign-in (Popup method) with Nuxt.js 3 - Works in Incognito mode as well

Add GSI client in your nuxt.config.ts
export default defineNuxtConfig({
  ...
  app: {
    head: {
      ...
      script: [
        {
          src: 'https://accounts.google.com/gsi/client',
        },
      ],
      ...
    }
  }
  ...
});
In your login page or component, add the Google Button div (this will be populated by the rendered button)
<div id="googleButton"></div>
Inside your mounted hook, initialize the Google Sign in and render the Sign in button
<template>
  <div id="googleButton"></div>
</template>
<script lang="ts" setup>

onMounted(() => {
   window.onload = () => {
    google.accounts.id.initialize({
      client_id: 'YOUR_CLIENT_ID',
      callback: handleCredentialResponse, //method to run after user clicks the Google sign in button
    });
    google.accounts.id.renderButton(
      document.getElementById("googleButton"),
      { theme: "outline", size: "large" } // customization attributes
    );
    google.accounts.id.prompt(); // also display the One Tap dialog
  }
})

function handleCredentialResponse(response) {
  // call your backend API here
  // the token can be accessed as: response.credential
}
</script>
@sarbjit-rnd
Copy link

google is not defined this error is populating , when I used this code.

@srestraj
Copy link
Author

google is not defined this error is populating , when I used this code.

Hi @sarbjit-rnd , if you're using Nuxt 3, you might want to install @types/google.accounts by doing npm i @types/google.accounts first and then use it in your component as /// <reference types='google.accounts' />

example:

<script lang="ts" setup>
/// <reference types='google.accounts' />

onMounted(() => {
   window.onload = () => {
    google.accounts.id.initialize({
      client_id: 'YOUR_CLIENT_ID',
      callback: handleCredentialResponse, //method to run after user clicks the Google sign in button
    });
    google.accounts.id.renderButton(
      document.getElementById("googleButton"),
      { theme: "outline", size: "large" } // customization attributes
    );
    google.accounts.id.prompt(); // also display the One Tap dialog
  }
})

const handleCredentialResponse = (response) => {
  // call your backend API here
  // the token can be accessed as: response.credential
}
</script>

I hope this helps.

@sarbjit-rnd
Copy link

sarbjit-rnd commented Mar 14, 2023 via email

@mbellemo
Copy link

google is not defined this error is populating , when I used this code.

Hi @sarbjit-rnd , if you're using Nuxt 3, you might want to install @types/google.accounts by doing npm i @types/google.accounts first and then use it in your component as /// <reference types='google.accounts' />

example:

<script lang="ts" setup>
/// <reference types='google.accounts' />

onMounted(() => {
   window.onload = () => {
    google.accounts.id.initialize({
      client_id: 'YOUR_CLIENT_ID',
      callback: handleCredentialResponse, //method to run after user clicks the Google sign in button
    });
    google.accounts.id.renderButton(
      document.getElementById("googleButton"),
      { theme: "outline", size: "large" } // customization attributes
    );
    google.accounts.id.prompt(); // also display the One Tap dialog
  }
})

const handleCredentialResponse = (response) => {
  // call your backend API here
  // the token can be accessed as: response.credential
}
</script>

I hope this helps.

The solution does not render the button. I suspect it is because the window object is not present on the client side.

const googleCallback = (response) => {
  const { credential } = response;
  emit("signedIn", credential);
};

watchEffect(() => {
  if (process.client) {
    if (window?.google) {
      window.google.accounts.id.initialize({
        client_id: config.public.GOOGLE_CLIENT_ID,
        callback: googleCallback,
      });

      window.google.accounts.id.renderButton(
        document.getElementById("buttonDiv"),
        {
          theme: "outline",
          size: "large",
          width: "384",
          text: props.text,
        }
      );
      window.google.accounts.id.prompt();
    }
  }
});

@srestraj
Copy link
Author

srestraj commented Mar 20, 2023

I think the code can also be written inside onMounted without the window object. Something I've implemented myself in one of my codes.

<script lang="ts" setup>
  /// <reference types='google.accounts' />
  onMounted(() => {
    google.accounts.id.initialize({
      client_id: GOOGLE_CLIENT_ID,
      callback: handleCredentialResponse,
      context: 'signin'
    })
    google.accounts.id.renderButton(
      document.getElementById("googleButton"), {
      type: 'standard',
      size: 'large',
      text: 'signin_with',
      shape: 'pill',
      logo_alignment: 'left',
      width: '250'
    }
    )
  })
  const handleCredentialResponse = (res) => {
    // login function
  }
</script>

@rmaniego
Copy link

onMounted(() => {
  setTimeout(() => {
    // let gsBtn = document.getElementById("googleButton")
    // if (gsBtn == null) return
     ...
  }, 0.5);
  })

I use this workaround...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment