I think this is a bit out of my skill set to get working properly.
Even if I did get it to work, I just realized that if a user has javascript disabled, then they won't be able to add products to the cart. Can't seem to find a current noscript fallback.
This makes me want to remove reCaptcha for our checkout as well.
Somehow we still have lots of users with javascript disabled.
Which is why we have noscript fallbacks all over our site.
I guess we will have to deal with the bot spam.
Or perhaps add a hidden field that won't allow forms to submit if it is filled out by a bot.
Thanks for the help anyways though.
Appreciate it.
Add Invisible reCaptcha v2 to PROD page for AJAX Add to Cart Form
Collapse
X
-
Okay.
Do i also need to change the add to cart button html to onsubmit? or just the function in the Scripts.js file?
Code:<span onclick="document.forms.add.action = '&mvtj:urls:BASK:auto;'; document.forms.add.elements.Action.value = 'ADPR';"> <input type="submit" value="Add to Cart" data-value="Add to Cart" id="js-add-to-cart" class="button button-block corners uppercase add-to-cart black bg-sky bold" /> </span>
Leave a comment:
-
Okay. Thanks guys.
I would prefer it to run after everything is validated.
That way the reCaptcha is only executed if all the required attributes are filled out or selected.
Would that be a similar situation as you suggested Matt?
Leave a comment:
-
I'm not really familiar with adding reCaptcha, however if you need that function to run prior to the submit, I would modify the add to cart function to be onSubmit of the form and add the execute call as an onClick of the button.
Leave a comment:
-
I'd think the most obvious point would be at the start. And if not true, just fail silently.
Leave a comment:
-
Add Invisible reCaptcha v2 to PROD page for AJAX Add to Cart Form
We get a lot of bot activity spamming our PROD page attributes which creates carts with spammy links and information.
So, to combat that, I would like to add the invisible recaptcha v2 to our PROD page for the Add to Cart form.
We are on the most current update for Miva running the Suivant ReadyTheme.
Here is what I have done so far using google's guide and some other more generic online guides:
Code Added to Head Tag:
Code for Add to Cart Form:Code:<script type="text/javascript"> var onSubmit = function(response) { document.getElementById("js-purchase-product").submit(); // send response to your backend service }; </script>
Code for AJAX Add to Cart in scripts.js fileCode:<form method="post" action="&mvte:urls:BASK:auto;" name="add" id="js-purchase-product"> <input type="hidden" name="Old_Screen" value="&mvte:global:Screen;" /> <input type="hidden" name="Old_Search" value="&mvte:global:Search;" /> <input type="hidden" name="Action" value="ADPR" /> <input type="hidden" name="Product_Code" value="&mvte:product:code;" /> <input type="hidden" name="Category_Code" value="&mvte:global:category_code;" /> <input type="hidden" name="Offset" value="&mvte:global:Offset;" /> <input type="hidden" name="AllOffset" value="&mvte:global:AllOffset;" /> <input type="hidden" name="CatListingOffset" value="&mvte:global:CatListingOffset;" /> <input type="hidden" name="RelatedOffset" value="&mvte:global:RelatedOffset;" /> <input type="hidden" name="SearchOffset" value="&mvte:global:SearchOffset;" /> <div class="row"> <mvt:if expr="l.settings:product:inv_active OR l.settings:attributemachine:product:inv_active"> <div id="js-inventory-message" class="column whole print-hide"> <p>&mvt:product:inv_long;</p> </div> </mvt:if> <div class="column whole"> <mvt:item name="customfields" param="Read_Product_Code( l.settings:product:code, 'familytree', g.familytree )" /> <mvt:if expr="NOT ISNULL g.familytree"> <div id="family-tree">&mvt:global:familytree;</div> </mvt:if> <mvt:item name="customfields" param="Read_Product_Code( l.settings:product:code, 'productbulletpoints', g.productbulletpoints )" /> <mvt:if expr="NOT ISNULL g.productbulletpoints"> <div>&mvt:global:productbulletpoints;</div> </mvt:if> <mvt:if expr="l.settings:product:code EQ 'EFTGH' OR l.settings:product:code EQ 'EFTSH'"> <div class="align-right"> <p class="italic">Done Adding Hearts to Your Tree?</p> <a href="https://&mvt:global:domain:name;/&mvte:product:code;.html#RelatedProducts" rel="nofollow" class="button corners bg-sky mbm1-25" style="white-space:normal;height:auto;line-height:1;padding:0.5rem">Click Here to Add Discs</a> </div> <mvt:elseif expr="l.settings:product:code EQ 'EFTGD' OR l.settings:product:code EQ 'EFTSD' OR l.settings:product:code EQ 'EFTDD' OR l.settings:product:code EQ 'EFTDA' OR l.settings:product:code EQ 'EFTADB' OR l.settings:product:code EQ 'EFTPD'"> <div class="align-right"> <p class="italic">Done Adding Discs to Your Tree?</p> <a href="https://&mvt:global:domain:name;/&mvte:product:code;.html#RelatedProducts" rel="nofollow" class="button corners bg-sky mbm1-25" style="white-space:normal;height:auto;line-height:1;padding:0.5rem">Click Here to Add Hearts</a> </div> </mvt:if> <div id="js-purchase-message" class="message message-warning purchase-message"></div> </div> <div id="js-product-attributes" class="column whole product-attributes mtp1-25 mbm1-25"> <!--[if gte IE 9]><!--> <script src="&mvte:global:theme_path;/js/jquery-3.4.0.min.js"></script> <!--<![endif]--> <mvt:item name="product_attributes" param="product:id" /> </div> <mvt:if expr="g.hasSwatches"> <div class="column whole product-swatches"> <label>&mvte:global:swatch_prompt;</label> <span id="js-swatch-name" class="bold swatch-name"> </span> <hr noshade /> <div id="js-swatches"></div> </div> </mvt:if> <div class="column whole np"> <div class="g-recaptcha" data-sitekey="SITE-KEY-XXXXXXXXXXXX" data-callback="onSubmit" data-badge="inline" data-size="invisible"></div> <script src="https://www.google.com/recaptcha/api.js" async defer></script> </div> <!-- end invisible recaptcha --> <a id="AddToCart"></a> </div> <div class="row corners add-to-cart-wrap bg-lt-gray"> <div class="column whole align-center"> <div class="bold">Price Subtotal<br /><span class="small normal">(with options added)</span></div> <mvt:if expr="l.settings:product:price GT 0"> <div id="js-price-value" class="h3 charcoal nm" data-base-price="&mvt:product:price;">&mvt:product:formatted_price;</div> <mvt:else> <div id="js-price-value" class="all-hidden" data-base-price="&mvt:product:price;"></div> </mvt:if> <br /> </div> <div class="column whole small-half medium-whole large-two-fifths x-large-three-tenths print-hide"> <div class="row quantity-wrap align-center"> <div class="column whole np"> <span id="js-decrease-quantity" class="bg-gray corners-left decrease-quantity" unselectable="on" data-rt-icon=""></span> <input type="tel" name="Quantity" value="1" id="l-quantity" class="align-center" style="font-size:1rem" /> <span id="js-increase-quantity" class="bg-gray corners-right increase-quantity" unselectable="on" data-rt-icon=""></span> </div> </div> <mvt:if expr="NOT l.settings:subscription:mandatory"> <div class="row align-center"> <div class="column whole np"> <span data-mmnodisable="true"> <span onClick="document.forms.add.action = '&mvtj:urls:WISH:secure;'; document.forms.add.elements.Action.value = 'ATWL';" class="small" data-rt-icon=""> <mvt:item name="buttons" param="AddToWishList" /> </span> </span> </div> </div> </mvt:if> </div> <div class="column whole small-half medium-whole large-three-fifths x-large-seven-tenths print-hide"> <div class="breaker small-all-hidden medium-all-shown large-all-hidden"></div> <mvt:comment> ========== for Attribute Magic module ========== </mvt:comment> <mvt:if expr="g.ATMG_Edit_Item"> <span onclick="document.forms.add.action = '&mvtj:urls:BASK:auto;'; document.forms.add.elements.Action.value = 'RGRP,ADPR';"> <input type="submit" value="Replace Item In Cart" data-value="Replace Item In Cart" id="add-to-cart" class="button button-block corners uppercase add-to-cart black bg-yellow bold" /> <input type="hidden" name="Basket_Group" value="&mvte:global:Basket_Group;" /> </span> <mvt:else> <span onclick="document.forms.add.action = '&mvtj:urls:BASK:auto;'; document.forms.add.elements.Action.value = 'ADPR';"> <input type="submit" value="Add to Cart" data-value="Add to Cart" id="js-add-to-cart" class="button button-block corners uppercase add-to-cart black bg-sky bold" /> </span> </mvt:if> </div> </div> </form>
Code:// ---- AJAX Add To Cart ---- // function addToCart () { $('#js-add-to-cart').on('click', function (e) { var purchaseForm = $('#js-purchase-product'); // Check the form is not currently submitting if (purchaseForm.data('formstatus') !== 'submitting') { // Set up variables var form = purchaseForm, formData = form.serialize(), randomNo = Math.ceil(Math.random() * 1000000), // IE Hack: Creating random number to refresh ajax call formUrl = form.attr('action'), formMethod = form.attr('method'), responseMessage = $('#js-purchase-message'), miniBasket = $('#js-mini-basket-container'), processingImage = $('#js-processing-purchase'), purchaseButton = $(this), purchaseButtonText = purchaseButton.val(); if (/\?/.test(formUrl)) { formUrl = formUrl + '&v=' + randomNo; } else { formUrl = formUrl + '?v=' + randomNo; }; // Add status data to form form.data('formstatus', 'submitting'); // Show processing message processingImage.show(); purchaseButton.toggleDisabled().val('Processing...'); responseMessage.html('').hide(); // Send data to server for validation $.ajax({ url: formUrl, type: formMethod, data: formData, success: function(data, textStatus, jqXHR) { if (data.search(/id="js-BASK"/i) != -1) { $('html, body').animate({scrollTop: '0px'}, 250); var responseMiniBasket = $(data).find('#js-mini-basket-container'), miniBasketCount = responseMiniBasket.contents()[1].getAttribute('data-itemcount'), miniBasketSubtotal = ' ' + responseMiniBasket.contents()[1].getAttribute('data-subtotal'), miniBasketLinkCount = $('#js-mini-basket-count, #js-mobile-basket-button .notification'), miniBasketLinkSubtotal = $('#js-mini-basket-subtotal'); miniBasketLinkCount.text(miniBasketCount); // Update basket quantity (display only) miniBasketLinkSubtotal.text(miniBasketSubtotal); // Update basket subtotal (display only) miniBasket.html(responseMiniBasket.contents()).addClass('open'); $('.mini-basket-table-wrap').scrollTop($('.mini-basket-table-wrap')[0].scrollHeight); setTimeout(function () { miniBasket.removeClass('open'); if ( $( "#family-tree" ).length ) { $(document).ready(function(){ var url = "/family-tree-hearts-discs.html"; $(location).attr('href',url); }); }; if ( $( "#wholesale-family-tree" ).length ) { $(document).ready(function(){ var url = "/wholesale-family-tree-hearts-discs.html"; $(location).attr('href',url); }); }; }, 3000); // Re-Initialize Attribute Machine (if it is active) if (typeof attrMachCall !== 'undefined') { attrMachCall.Initialize(); }; } else if(data.search(/id="js-PATR"/i) != -1) { var missingAttrs = []; form.find('.required').each(function () { missingAttrs.push(' ' + $(this).attr('title')); }); responseMessage.html('All <em class="red">Required</em> options have not been selected.<br />Please review the following options: <span class="red">' + missingAttrs + '</span>.').fadeIn(); $('html, body').animate({scrollTop: ($('#js-purchase-message').offset().top - 100)},500); } else if(data.search(/id="js-PLMT"/i) != -1) { responseMessage.html('We do not have enough of the Size/Color you have selected.<br />Please adjust your quantity.').fadeIn().delay(3000).fadeOut(); $('html, body').animate({scrollTop: ($('#js-inventory-message').offset().top - 100)},500); } else if(data.search(/id="js-POUT"/i) != -1) { responseMessage.html('The Size/Color you have selected is out of stock.<br />Please review your options or check back later.').fadeIn().delay(3000).fadeOut(); $('html, body').animate({scrollTop: ($('#js-inventory-message').offset().top - 100)},500); } else { responseMessage.html('Please review options.').fadeIn().delay(3000).fadeOut(); $('html, body').animate({scrollTop: ($('#js-purchase-message').offset().top - 100)},500); }; // Hide processing message and reset formstatus processingImage.hide(); purchaseButton.toggleDisabled().val(purchaseButtonText); form.data('formstatus', 'idle'); }, error: function (jqXHR, textStatus, errorThrown) { } }); }; // Prevent form from submitting e.stopImmediatePropagation(); e.preventDefault(); }); }; var addToCart = new addToCart;
The trouble I am having is:
Where do I add grecaptcha.execute();?
I want to keep the functionality of the AJAX Add to Cart and Form Validation.
Here is a link to a product page for reference: https://www.loveisarose.com/ILYR11.html
Thanks in advance for any help or light shed on the situation.
Leave a comment: