PHPackages                             superrb/google-recaptcha - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. superrb/google-recaptcha

ActiveLibrary[Security](/categories/security)

superrb/google-recaptcha
========================

Symfony 4 Google Recaptcha Integration

1.1.1(3y ago)04.7k1MITPHP

Since Jun 24Pushed 3y ago4 watchersCompare

[ Source](https://github.com/superrbstudio/symfony-google-recaptcha)[ Packagist](https://packagist.org/packages/superrb/google-recaptcha)[ Docs](https://github.com/superrbstudio/symfony-google-recaptcha)[ RSS](/packages/superrb-google-recaptcha/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (2)Versions (10)Used By (1)

Google Recaptcha
================

[](#google-recaptcha)

Google Recaptcha v3 Symfony 4 Bundle

Installation
------------

[](#installation)

`composer require superrb/google-recaptcha`

Create the following environment variables:

```
###> superrb/google-recaptcha ###
SUPERRB_GOOGLE_RECAPTCHA_SITE_KEY="Get From https://www.google.com/recaptcha/intro/v3.html"
SUPERRB_GOOGLE_RECAPTCHA_SECRET_KEY="Get From https://www.google.com/recaptcha/intro/v3.html"
###< superrb/google-recaptcha ###
```

Add the validator to your form, this will create a hidden field that we must put the returned token in to allow server side verification.

```
use Superrb\GoogleRecaptchaBundle\Validator\Constraint\GoogleRecaptcha;

// ...

public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...
    $builder->add('recaptcha', HiddenType::class, [
        'attr' => [
            'class' => 'superrb-google-recaptcha',
        ],
        'constraints' => [
            new GoogleRecaptcha(),
        ],
    ]);
}
```

The class is important as it is used to identify the field on the front end when using the standard integration. If you are creating your own frontend integration then you can identify the field in your own way.

Front End Integration
---------------------

[](#front-end-integration)

### Standard Integration

[](#standard-integration)

You can use the following Twig function to output the standard frontend integration. This will automatically generate a token and add it to the hidden field. This is the simplest integration however it does come with some caveats:

- If the form errors the token will now be invalid and can't be used again. You could empty the field in your controller after an error and it will be repopulated.
- The token will expire after 2 minutes. If your form is long it could expire before the form is submitted and the user will fail validation.

```
{{ google_recaptcha_standard_integration() | raw }}
{{ form_start(form) }}
{{ form_end(form) }}
```

### Javascript (Compatible with Turbolinks)

[](#javascript-compatible-with-turbolinks)

Create a constant for the site key and create a container to hold the configuration. This should be put in your layout so that it is always available when using Turbolinks, if you aren't using Turbolinks then it only needs to be on the page with the form you are protecting.

```
const RECAPTCHA_KEY = '{{ google_recaptcha_site_key() }}';

```

Use this Javascript component and customise to your needs

```
import LiveNodeList from 'live-node-list'
import {bind} from 'decko'
import { load as loadRecaptcha } from 'recaptcha-v3'

export default class GoogleRecaptcha {
  forms = new LiveNodeList('form.form--contact')

  constructor () {
    this.registerListeners()
  }

  @bind
  handleSubmit (e) {
    const recaptchaInput = document.querySelector('input.superrb-google-recaptcha')
    if (recaptchaInput && !recaptchaInput.value) {
      e.preventDefault()
      e.stopPropagation()
      return this.setupRecaptcha(e)
    }

    return true
  }

  @bind
  async setupRecaptcha(e) {
    const recaptchaInput = document.querySelector('input.superrb-google-recaptcha')
    if (recaptchaInput) {
      // Load recaptcha library
      if (!window.recaptcha) {
        window.recaptcha = await loadRecaptcha('explicit', {autoHideBadge: true})
        this.recaptchaHandle = grecaptcha.render('recaptcha-container', {
          'sitekey': RECAPTCHA_KEY,
          'badge': 'inline', // must be inline
          'size': 'invisible' // must be invisible

        })
      }

      // Get a recaptcha token
      const token = await window.grecaptcha.execute(this.recaptchaHandle)

      // Append the recaptcha token to the form
      recaptchaInput.value = token

      const form = e.currentTarget || e.target
      form.submit()
    }
  }

  @bind
  registerListeners() {
    const recaptchaInput = document.querySelector('input.superrb-google-recaptcha')
    if(recaptchaInput) {
      recaptchaInput.value = null
    }

    this.forms.addEventListener('submit', this.handleSubmit)
  }
}
```

### Ajax form using jQuery

[](#ajax-form-using-jquery)

Load the library and create a global constant for the site key:

```
{{ google_recaptcha_output_src() | raw }}
const RECAPTCHA_KEY = '{{ google_recaptcha_site_key() }}';
```

Bind a jQuery event to the form submit that generates a token and inserts it into the hiden field

```
$('form').unbind('submit').submit(function(e){
    e.preventDefault();
    var form = $(this);

    // get the token
    grecaptcha.ready(function() {
        grecaptcha.execute(RECAPTCHA_KEY, {action: 'homepage'}).then(function (token) {
            // add the token to the hidden field
            $('input.superrb-google-recaptcha').val(token);

            // Process and submit form
        });
    });
});
```

Issues and Troubleshooting
--------------------------

[](#issues-and-troubleshooting)

All issues:

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity17

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~155 days

Recently: every ~303 days

Total

9

Last Release

1278d ago

Major Versions

0.0.1 → 1.0.02019-06-25

### Community

Maintainers

![](https://www.gravatar.com/avatar/854ddd08c308e3eb27145572f8c872a4170049243b2c1e82a89ac2cdc57317c3?d=identicon)[superrb](/maintainers/superrb)

---

Top Contributors

[![iknowfoobar](https://avatars.githubusercontent.com/u/255807?v=4)](https://github.com/iknowfoobar "iknowfoobar (13 commits)")

---

Tags

cms

### Embed Badge

![Health badge](/badges/superrb-google-recaptcha/health.svg)

```
[![Health](https://phpackages.com/badges/superrb-google-recaptcha/health.svg)](https://phpackages.com/packages/superrb-google-recaptcha)
```

###  Alternatives

[open-dxp/opendxp

Content &amp; Product Management Framework (CMS/PIM)

7310.3k29](/packages/open-dxp-opendxp)[craftpulse/craft-password-policy

Password Policy plugin

2826.0k1](/packages/craftpulse-craft-password-policy)[born05/craft-csp

Content Security Policy (or CSP) generator using nonces.

1110.2k](/packages/born05-craft-csp)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
