solspace / craft-freeform

Freeform for Craft: The most reliable form builder that's ready for wherever your project takes you.
https://docs.solspace.com/craft/freeform/v5/
Other
47 stars 59 forks source link

Recaptcha V2 Checkbox Settings #1222

Closed gjhead closed 5 months ago

gjhead commented 5 months ago

With the new way that ReCaptcha is rendered in FreeForm5, it's breaking some existing functions on my website.

We currently use ReCaptcha v2 Checkbox, primarily so that we can avoid multiple and/or incomplete submissions to HubSpot. Previously, we were rendering the "g-recaptcha" container in our templates, so that we could set the "data-callback" name. But we are no longer able to do this unless we set up ReCaptcha outside of Freeform - and this is not idea as it removed any server-side ReCaptcha functionality.

is there anyway to set an option(s) in freeform to also optionally set some of the g-recaptcha tag attributes like "data-callback"?

gustavs-gutmanis commented 5 months ago

Hi @gjhead

I'm sorry this change affected you. Could you describe your use case a little bit more, please, so I could come up with a good solution? Does the callback need to block the form submit from happening while it's processing?

One option would be to dispatch an event in javascript that would let you alter the .g-recaptcha element, and that would allow you to add the data-callback attribute, but that would not block the submit thread.

gjhead commented 5 months ago

@gustavs-gutmanis thanks for the reply -

In this specific example, I am disabling the submit button. When the recaptcha passes, I re-enable the submit button.

Also as a side note, I need to do more than this now, as it seems Freeform now automatically removes the "disabled" attribute from a button that has "type=submit" on it .

(When the Hubspot tracking code is on a site, it will completely take over the form Submit button and anytime someone click the submit button, it will submit the form into HubSpot as a "Non-Hubspot Form" - even if there are validation errors. It's incredibly annoying.)

One option would be to dispatch an event in javascript that would let you alter the .g-recaptcha element, and that would allow you to add the data-callback attribute, but that would not block the submit thread.

I considered this - but thought it may be affected by timing. But now with a clearer head that may work. Let me try it out today and get back to you.

Thanks!

gustavs-gutmanis commented 5 months ago

@gjhead as of a couple versions ago, we introduced a feature letting you block the submit thread with async callbacks. Here's a crude example, you could try using this:

document.addEventListener(events.form.submit, (event: FreeformEvent) => {
  // The default priority is 0
  // The lesser the priority, the faster it will be called,
  // So priority 10 will be called after all of priority `0` functions have been called
  // Which in turn will be called after all of priority `-10` functions have been called
  const priority = 10;
  event.addCallback(async () => {
    const form = event.form;

    await yourAsyncFunction();

    // You can either return `true` or nothing and it will submit successfully
    // or you can return `false` and the submit won't execute
  }, priority);
});
gjhead commented 5 months ago

Digging back into this tomorrow morning. If we can keep this issue open for at least another day it would be appreciated. Will report back shortly. Thanks @gustavs-gutmanis

gustavs-gutmanis commented 5 months ago

Sure thing @gjhead

gjhead commented 5 months ago

Well, not much luck trying to get this to work with the native FreeForm integration. Can't seem to add that data-callback and get it to work, even adding via the render tag.

I think my only option here is to bypass FreeForm's integration of Recaptcha V2 and instead add it manually in my templates. This whole process is to keep that submit button deactivated anyway because that is the trigger that Hubspot uses to submit a Non-hubspot form. Looking back on this, I'm trying to use Freeform to control a brand new layer on top of the form that it can't control anyway. Freeform is just capturing submissions as a backup, so I'll still use the honeypot feature to combat any spam that way.

Thanks for following along with me. I think this situation is just unique to my client and the way Hubspot's tracking code deals with non-hubspot forms. (Ideally, I would be able to turn this feature off and just submit directly to the Hubspot API, but that's not an option for me right now.)

Thanks, @gustavs-gutmanis !

gustavs-gutmanis commented 5 months ago

Sorry this didn't work out @gjhead But just out of curiosity, did you try the javascript I mentioned above?

@gjhead as of a couple versions ago, we introduced a feature letting you block the submit thread with async callbacks. Here's a crude example, you could try using this:

document.addEventListener(events.form.submit, (event: FreeformEvent) => {
  // The default priority is 0
  // The lesser the priority, the faster it will be called,
  // So priority 10 will be called after all of priority `0` functions have been called
  // Which in turn will be called after all of priority `-10` functions have been called
  const priority = 10;
  event.addCallback(async () => {
    const form = event.form;

    await yourAsyncFunction();

    // You can either return `true` or nothing and it will submit successfully
    // or you can return `false` and the submit won't execute
  }, priority);
});

This lets you add code before and after honeypots, recaptchas, etc, that lets you do something synchronous and block the form submit from finishing or executing next things, and then finish it by returning a resolved or rejected promise.

In your case, since you want to execute hubspot logic after recaptcha - you would add a priority of > 0, I would suggest 10.

document.addEventListener("freeform-on-submit", (event: FreeformEvent) => {
  const priority = 10;
  event.addCallback(async () => {
    const form = event.form;

    const data = { firstName: form.firstName.value };
    const response = await axios.post('https://your-hubspot-endpoint', data);

    if (response.status === 201) {
      form.hiddenHubSpotField.value = response.data.id;

      return true;
    }

    alert('There was an error');

    return false;
  }, priority);
});

In this example the form would submit, perform the fetching of recaptcha token, setting it, then it would execute your hubspot code, set the hidden field ID, then it would submit, and assuming that the form is valid, it would finish successfully.

This does bring a nasty problem though, any validation of the submitted data would happen after the hubspot push, which isn't something you can bypass right now. We are planning on adding an enpoint where you can validate your form data without actually submitting the form, then you would be able to call that, and assuming there are no errors - go along with the hubspot save.

gjhead commented 5 months ago

I'll give it a shot. This follow-up explains it a bit better. Thanks!

gustavs-gutmanis commented 5 months ago

Sorry the events.form.submit should be "freeform-on-submit", I will edit the comment.