How to integrate Google reCAPTCHA in your Laravel project

Rajesh Dewle | 6 May 2020

I just finished a project using Laravel as a backend and Nuxt.js for front-end for a client. In this project, there was a requirement of integrating Google reCAPTCHA with the contact form. So I had to create a validation rule & register it via the service provider.

After a few days, my friend @swapnil_bhavsar suggested me a PHP package development course by @marcelpociot.

After the enjoying course, I realized that I should make a package for Google reCAPTHCHA integration. So that it can be used for other Laravel projects. And within a few hours, we developed a new package that can help us to integrate Google reCAPTCHA in just a few steps and it is currently available on Github at chitranu/google-recaptcha.

Introducation

In this tutorial, I'll show how to integrate chitranu/google-recaptcha package with your Laravel project and will show a few examples on how to using it in frontend using Vue.js.

Get site key & secret key

First, you will need to register your site to get the reCAPTCHA site key and secret key from Google. Go to the https://www.google.com/recaptcha/admin/create and log in.

Here is a registration form for your site, fill up the fields that very simple.

  • First, add label Eg. example.com that will make it easy for you to identify the site in the future.
  • After that, you need to select reCAPTCHA type.
  • Next, add domains in domains field where you want to use that reCAPTCHA. You can also add here localhost for testing on your local machine.
  • Then accept the reCAPTCHA terms of service and hit the submit button.
  • Now you have a site key and secret key.

Now its time to setup Laravel backend

Place the secret key inside .env file:

GOOGLE_RECAPTCHA_SECRETKEY=YOUR_RECAPTCHA_SECRET_KEY

Let's start with use composer to install chitranu/google-recaptcha package. Run the following command in your project directory:

$ composer require chitranu/google-recaptcha

After installed package you will need to add validation rule recaptcha shown below to validate then received token.

$request->validate([
    '...' // other fields
    'recaptcha-token' => 'required|recaptcha'
]);

If you are getting a lot of spam submissions, you can take advantage of setting the score threshold while specifying the validation rule by setting a value between 0.1 - 1.0. Read more about score threshold on google official guide (see here).

$request->validate([
    '...' // other fields
    'recaptcha-token' => 'required|recaptcha:0.5' // Specify threshhold
]);

All things are done in the backend.

Frontend (Using vue-recaptcha-v3)

Run the following command in your Nuxt.js or Vue.js project directory to install vue-recaptcha-v3 library. It is a simple and easy to use reCAPTCHA (v3 only) library.

With NPM:

$ npm install vue-recaptcha-v3

With Yarn:

$ yarn add vue-recaptcha-v3
Using Vue.js

If you are using Vue.js, You need to add the following code inside main.js file.

import Vue from 'vue';
import { VueReCaptcha } from 'vue-recaptcha-v3';
Vue.use(VueReCaptcha, {
  siteKey: 'ADD_HERE_GOOGLE_SITE_KEY',
  loaderOptions: {
    autoHideBadge: true
  }
})

Form component:

<template>
  <form @submit.prevent="onFormSubmit()" ref="contactform">
    <input type="text" name="name" placeholder="Your Name" />
    <input type="email" name="email" placeholder="Your Email" />
    <textarea name="message" placeholder="Your Message"></textarea>
    <p>
      This site is protected by reCAPTCHA and the Google
      <a href="https://policies.google.com/privacy">Privacy Policy</a> and
      <a href="https://policies.google.com/terms">Terms of Service</a> apply.
    </p>
    <button type="submit">Submit</button>
  </form>
</template>

<script>
export default {
  methods: {
    async onFormSubmit() {
      // Wait until recaptcha has been loaded.
      await this.$recaptchaLoaded();

      // Execute reCAPTCHA with action "login".
      const token = await this.$recaptcha('login');

      // Prepare form data
      let formData = new FormData(this.$refs.contactform);

      // Appended token in formData
      formData.append('recaptcha-token', token);

      // Make an ajax request to your Laravel endpoint.
      axios.post('/your-form-endpoint', formData).then(
        (response) => {
          // handle response
        },
        (error) => {
          // handle errors
        }
      );
    },
  },
};
</script>
Using Nuxt.js

If you are using Nuxt.js, You need to create a new plugin, For that create a new file in /plugins/vue-recaptcha.js and add the following code.

import Vue from 'vue' import;
{ VueReCaptcha } from 'vue-recaptcha-v3';
Vue.use(VueReCaptcha, {
  siteKey: 'ADD_HERE_GOOGLE_SITE_KEY',
  loaderOptions: {
    autoHideBadge: true
  }
})

Then add the file path inside the plugins key in nuxt.config.js

export default { plugins: ['~/plugins/vue-recaptcha'] }

Form component:

<template>
  <form @submit.prevent="onFormSubmit()" ref="contactform">
    <input type="text" name="name" placeholder="Your Name" />
    <input type="email" name="email" placeholder="Your Email" />
    <textarea name="message" placeholder="Your Message"></textarea>
    <p>
      This site is protected by reCAPTCHA and the Google
      <a href="https://policies.google.com/privacy">Privacy Policy</a> and
      <a href="https://policies.google.com/terms">Terms of Service</a> apply.
    </p>
    <button type="submit">Submit</button>
  </form>
</template>

<script>
export default {
  methods: {
    async onFormSubmit() {
      // Wait until recaptcha has been loaded.
      await this.$recaptchaLoaded();

      // Execute reCAPTCHA with action "login".
      const token = await this.$recaptcha('login');

      // Prepare form data
      let formData = new FormData(this.$refs.contactform);

      // Appended token in formData
      formData.append('recaptcha-token', token);

      // Make an ajax request to your Laravel endpoint.
      this.$axios.$post('/your-form-endpoint', formData).then(
        (response) => {
          // handle response
        },
        (error) => {
          // handle errors
        }
      );
    },
  },
};
</script>

We are using here autoHideBadge: true loaderOptions, that can be hide google reCAPTCHA badge.

Warning: The badge hide usage is only allowed if you follow the google official guide (see here)for the badge hide. As per Google policy, you need to include the following text where you want to use Google reCAPTCHA:

This site is protected by reCAPTCHA and the Google
<a href="https://policies.google.com/privacy">Privacy Policy</a> and
<a href="https://policies.google.com/terms">Terms of Service</a> apply.

Otherwise, you can show them on your webpage. Just change the autoHideBadge: false.

In the above example, I added a simple form. After the hit submit button onFormSubmit() method will be the trigger. In this method first, execute reCAPTCHA, then prepare the contact data in the formData variable. Then appended the received token in that formData with the recaptcha-token key. Next sent the post request using the axios to the API endpoint with form data.

Frontend (Using vue-recaptcha)

Run the following command in your Nuxt.js or Vue.js project directory to install vue-recaptcha library. It is a simple and easy to use reCAPTCHA (v2 only) library.

$ npm install vue-recaptcha-v3

Next add form component:

<template>
  <form @submit.prevent="onFormSubmit()" ref="contactform">
    <input type="text" name="name" placeholder="Your Name" />
    <input type="email" name="email" placeholder="Your Email" />
    <textarea name="message" placeholder="Your Message"></textarea>
    <vue-recaptcha
      ref="recaptcha"
      @verify="onCaptchaVerified"
      @expired="resetCaptcha"
      :sitekey="sitekey"
      :loadRecaptchaScript="true"
    />
    <button type="submit">Submit</button>
  </form>
</template>

<script>
import VueRecaptcha from 'vue-recaptcha';

export default {
  components: {
    VueRecaptcha,
  },
  computed: {
    sitekey() {
      return 'YOUR_GOOGLE_RECAPTHCA_SITE_KEY';
    },
  },
  methods: {
    onFormSubmit() {
      this.$refs.recaptcha.execute();
    },
    onCaptchaVerified(token) {
      // Prepare form data
      const formData = new FormData(this.$refs.contactform);

      // Appended token in formData
      formData.append('recaptcha-token', token);

      // Make an ajax request to your Laravel endpoint.
      axios.post('/your-form-endpoint', formData).then(
        (response) => {
          // handle response
        },
        (error) => {
          // handle errors
        }
      );
    },
    resetCaptcha() {
      this.$refs.recaptcha.reset();
    },
  },
};
</script>

All things are done.