Skip to content

Instantly share code, notes, and snippets.

@srestraj
Last active June 21, 2025 02:04
Show Gist options
  • Select an option

  • Save srestraj/c61d0a025f53ab7f99bd875eace5cc84 to your computer and use it in GitHub Desktop.

Select an option

Save srestraj/c61d0a025f53ab7f99bd875eace5cc84 to your computer and use it in GitHub Desktop.
Integrate Google Sign-in and One-tap with Nuxt.js

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

Nuxt 3 version here.
Add GSI client in your nuxt.config.js
export default {
  ...
  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>

export default {
  mounted() {
    // initialize Google Sign in  
    google.accounts.id.initialize({
        client_id: 'YOUR_CLIENT_ID',
        callback: this.handleCredentialResponse, //method to run after user clicks the Google sign in button
        context: 'signin'
      })
    
    // render button
    google.accounts.id.renderButton(
      document.getElementById('googleButton'),
      { 
        type: 'standard',
        size: 'large',
        text: 'signin_with',
        shape: 'rectangular',
        logo_alignment: 'center',
        width: 250
      }
    )
  },
  
  methods: {
    handleCredentialResponse(response) {
    
      // call your backend API here
      
      // the token can be accessed as: response.credential
    }
  }
}
</script>
If you also want the Google One-tap sign in, use the following inside the component or page you want to display one-tap.
<template>
...
</template>
<script>
  export default {
    mounted() {
      google.accounts.id.initialize({
        client_id: 'YOUR_CLIENT_ID',
        callback: this.handleCredentialResponse,
        context: 'signin',
      })
      google.accounts.id.prompt()
    },
    
    methods: {
      handleCredentialResponse(response) {
        // handle API calls same as above
      }
    }
  }
</script>
@srestraj

srestraj commented Jun 3, 2022

Copy link
Copy Markdown
Author

Hi, @Huucong95 Did you whitelist your localhost domains? You'd need to explicitly add both http://localhost and http://localhost:3000 to your authorized domains as mentioned here.

I hope this helps.

@dhairyanatahn

Copy link
Copy Markdown

getting an error as google is not defined

@srestraj

srestraj commented Sep 8, 2022

Copy link
Copy Markdown
Author

getting an error as google is not defined

This is because you're trying to access the "google" property before it's injected and accessible. You need to wait for Google SDK to load so the "google" property is injected into the window object.

Can you include a screenshot of your implementation or create a reproduction in StackBlitz or Codepen?

@ap-1

ap-1 commented Sep 27, 2022

Copy link
Copy Markdown

I'm getting the same error as @dhairyanatahn, although I'm using Nuxt 3 RC 11 along with its Composition API:
image

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
	/* snip */
	head: {
		script: [
			{ src: "https://apis.google.com/js/api.js" },
			{ src: "https://accounts.google.com/gsi/client" },
		],
	},
});
<!-- login.vue -->
<script setup lang="ts">
import { useAuthStore } from '~/stores/auth';

const { signInNew, signOut } = useAuthStore();

onMounted(() => {
	google.accounts.id.initialize({
		client_id: "id.apps.googleusercontent.com",
		callback: signInNew,
	});

	google.accounts.id.renderButton(document.getElementById("signIn")!, {
		type: "standard",
	});
	google.accounts.id.prompt();
});
</script>

<template>
	<div>
		<button id="signIn"></button>
		<button @click="signOut">Sign out</button>
	</div>
</template>

@srestraj

srestraj commented Sep 29, 2022

Copy link
Copy Markdown
Author

I'm getting the same error as @dhairyanatahn, although I'm using Nuxt 3 RC 11 along with its Composition API: image

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
	/* snip */
	head: {
		script: [
			{ src: "https://apis.google.com/js/api.js" },
			{ src: "https://accounts.google.com/gsi/client" },
		],
	},
});
<!-- login.vue -->
<script setup lang="ts">
import { useAuthStore } from '~/stores/auth';

const { signInNew, signOut } = useAuthStore();

onMounted(() => {
	google.accounts.id.initialize({
		client_id: "id.apps.googleusercontent.com",
		callback: signInNew,
	});

	google.accounts.id.renderButton(document.getElementById("signIn")!, {
		type: "standard",
	});
	google.accounts.id.prompt();
});
</script>

<template>
	<div>
		<button id="signIn"></button>
		<button @click="signOut">Sign out</button>
	</div>
</template>

Hi @ap-1

for Nuxt 3, you can follow this:

Since Nuxt 3 has changed things a bit, to include the GSI tag in the <head></head> tag, you now have to either use the pre-provided <Head></Head> tag - documentation, or useHead - documentation or, for nuxt.config.ts, you can use it inside app https://v3.nuxtjs.org/api/configuration/nuxt.config#app. For now, I've used the app method.

Include the GSI script tag inside nuxt.config.ts.

export default defineNuxtConfig({
...
  app: {
    head: {
      script: [
        {
          src: 'https://accounts.google.com/gsi/client'
        }
      ]
    }
  },
...
})

Then, in your component or page:

onMounted(() => {
  initializeGoogleSignIn()
})
function initializeGoogleSignIn() {
  if (config.public.GOOGLE_CLIENT_ID != null || '') {
    google.accounts.id.initialize({
      client_id: config.GOOGLE_CLIENT_ID,
      callback: handleCredentialResponse, //method to run after user clicks the Google sign in button
      context: 'signin'
    })
    google.accounts.id.prompt()
  }
}

function handleCredentialResponse(response) {
  console.log(response)
}

I hope this helps.

@timba64

timba64 commented Dec 1, 2022

Copy link
Copy Markdown

It would be interesting if you show how to make custom button, without google renderButton() :-)

@srestraj

Copy link
Copy Markdown
Author

@timba64 Unfortunately, I've also not figured this one out yet, LOL

@thomasrobertm

Copy link
Copy Markdown

hello! I am having the following problem, It says that google is not defined, and I followed all of your steps mentioned above. any help :)?
image

@srestraj

srestraj commented Jan 16, 2023

Copy link
Copy Markdown
Author

Hi @thomasrobertm , are you using Vue 2 or Vue 3? For Vue 2, you might want to add window. in front of google. This might solve your issue. You can also check if you have added the GSI client in your nuxt.config.js.

@Armogo

Armogo commented Feb 2, 2023

Copy link
Copy Markdown

I use it in Nuxt 2 project and it worked, thanks a lot!

@ivanhttps

Copy link
Copy Markdown

Hey, I successfully logged in with your code snippet. What I should to do with response in callback? I need to get user info, how to do this? @srestraj

@srestraj

Copy link
Copy Markdown
Author

Hi @Daewon25 , once you get back the response from the callback, you'd need to pass it to backend for handling. However, if you want to extract the user details from the token you receive in the frontend itself and pass them to the backend, you can do that using jwt-decode.

For example:

<script>
import jwt_decode from 'jwt-decode'

export default {
    ...
  
  methods: {
    handleCredentialResponse(response) {      
      // the token can be accessed as: response.credential
      const token = jwt_decode(response.credential)
      console.log(`ID: ${token.sub}`)
      console.log(`Full Name: ${token.name}`)
      console.log(`Given Name: ${token.given_name}`)
      console.log(`Family Name: ${token.family_name}`)
      console.log(`Image URL: ${token.picture}`)
      console.log(`Email: ${token.email}`)
    }
  }
}
</script>

@ivanhttps

Copy link
Copy Markdown

@srestraj thanks a lot!

@Fanreza

Fanreza commented Jul 4, 2023

Copy link
Copy Markdown

anyone have example without the google button?

@srestraj

srestraj commented Jul 7, 2023

Copy link
Copy Markdown
Author

@Fanreza, if you set the ux_mode to redirect and then handle the response server-side, you can create your own custom button. More about this here: https://developers.google.com/identity/gsi/web/reference/js-reference#ux_mode. You can also have a look at this for other options: https://developers.google.com/identity/gsi/web/reference/html-reference. If you want to use it with the pop_up mode itself, I think you can try hiding the default Google button with visibility: hidden or opacity: 0 and then add your custom button. Something like we do for custom file inputs. I haven't tried it myself, but it might work I think.

@Fanreza

Fanreza commented Jul 10, 2023

Copy link
Copy Markdown

@Fanreza, if you set the ux_mode to redirect and then handle the response server-side, you can create your own custom button. More about this here: https://developers.google.com/identity/gsi/web/reference/js-reference#ux_mode. You can also have a look at this for other options: https://developers.google.com/identity/gsi/web/reference/html-reference. If you want to use it with the pop_up mode itself, I think you can try hiding the default Google button with visibility: hidden and then add your custom button. Something like we do for custom file inputs. I haven't tried it myself, but it might work I think.

i think it will work, google button basically just a button right, we can programatically click it using javascript

@HalaSalim77

Copy link
Copy Markdown

hi, the login by google button is disapper suddenly and i got this error :

client:128 Uncaught Error
at _.$e (client:128:335)
at new sp (client:227:3)
at bq (client:246:34)
at Oo (client:244:246)
at Object.Po [as renderButton] (client:216:62)
at :8:24
at Object.insertBefore (93a0d79.js:2:45811)
at _ (93a0d79.js:2:59423)
at 93a0d79.js:2:58702
at m (93a0d79.js:2:58934)

what is the problem and how  i can fix it ?

@jirayuboss

Copy link
Copy Markdown

hi, the login by google button is disapper suddenly and i got this error :

client:128 Uncaught Error at _.$e (client:128:335) at new sp (client:227:3) at bq (client:246:34) at Oo (client:244:246) at Object.Po [as renderButton] (client:216:62) at :8:24 at Object.insertBefore (93a0d79.js:2:45811) at _ (93a0d79.js:2:59423) at 93a0d79.js:2:58702 at m (93a0d79.js:2:58934)

what is the problem and how  i can fix it ?

I also have the same issue. Did you find a way to fix it? Please help.

@srestraj

srestraj commented Aug 2, 2023

Copy link
Copy Markdown
Author

client:128 Uncaught Error
at _.$e (client:128:335)
at new sp (client:227:3)
at bq (client:246:34)
at Oo (client:244:246)
at Object.Po [as renderButton] (client:216:62)
at :8:24
at Object.insertBefore (93a0d79.js:2:45811)
at _ (93a0d79.js:2:59423)
at 93a0d79.js:2:58702
at m (93a0d79.js:2:58934)

Hi @HalaSalim77, could you send us the code snippet you have set up? Thanks.

@srestraj

srestraj commented Aug 4, 2023

Copy link
Copy Markdown
Author

Hi @HalaSalim77 and @jirayuboss , it looks like the issue is happening from the Google's side itself. As mentioned here: google/google-api-javascript-client#873 (comment), if you remove the width property or add px to it, it's fixed again. example:

google.accounts.id.renderButton(
      document.getElementById("gBtn"), {
        type: 'standard',
        size: 'large',
        text: 'signup_with',
        shape: 'pill',
        logo_alignment: 'left',
        width: '250px'
      }
)

I hope this helps.

@DwbpleaseCallMe

Copy link
Copy Markdown

Hello. I just want to display Google one tap on the website.

When I used your method to fix my nuxt2 project, there was no button on my website, but it was successful on other vue2 projects

//nuxt.config.js
{
src: 'https://accounts.google.com/gsi/client',
async: true,
defer: true,
},

//index.vue
mounted() {

setTimeout(() => {
  if (window.google && !this.token) {
    window.google.accounts.id.initialize({
      client_id: 'xxx',
      callback: this.handleGoogleOneTapCallback,
      context: 'signin',
    });
    window.google.accounts.id.prompt();


  }

}, 3000);

},

@srestraj

Copy link
Copy Markdown
Author

Hello. I just want to display Google one tap on the website.

When I used your method to fix my nuxt2 project, there was no button on my website, but it was successful on other vue2 projects

//nuxt.config.js { src: 'https://accounts.google.com/gsi/client', async: true, defer: true, },

//index.vue mounted() {

setTimeout(() => {
  if (window.google && !this.token) {
    window.google.accounts.id.initialize({
      client_id: 'xxx',
      callback: this.handleGoogleOneTapCallback,
      context: 'signin',
    });
    window.google.accounts.id.prompt();


  }

}, 3000);

},

@DwbpleaseCallMe, what's the error that you're seeing?

@DwbpleaseCallMe

Copy link
Copy Markdown

Hello. I just want to display Google one tap on the website.
When I used your method to fix my nuxt2 project, there was no button on my website, but it was successful on other vue2 projects
//nuxt.config.js { src: 'https://accounts.google.com/gsi/client', async: true, defer: true, },
//index.vue mounted() {

setTimeout(() => {
  if (window.google && !this.token) {
    window.google.accounts.id.initialize({
      client_id: 'xxx',
      callback: this.handleGoogleOneTapCallback,
      context: 'signin',
    });
    window.google.accounts.id.prompt();


  }

}, 3000);

},

@DwbpleaseCallMe, what's the error that you're seeing?

There was no error, it's just that there are no buttons displayed on the page

@srestraj

Copy link
Copy Markdown
Author

Hi @DwbpleaseCallMe, to display the button, you'd need to add the following as well.

setTimeout(() => {
  if (window.google && !this.token) {
    window.google.accounts.id.initialize({
      client_id: 'xxx',
      callback: this.handleGoogleOneTapCallback,
      context: 'signin',
    });

    // for button rendering
    window.google.accounts.id.renderButton(
      document.getElementById('googleButton'), // here, replace "googleButton" with the ID of your element that you want to populate with GSI.
      { 
        type: 'standard',
        size: 'large',
        text: 'signin_with',
        shape: 'rectangular',
        logo_alignment: 'center',
        width: '250px'
      }
    );
    window.google.accounts.id.prompt();


  }

}, 3000);

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