diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 # yesod-recaptcha2
 
 ![Hackage](https://img.shields.io/hackage/v/yesod-recaptcha2.svg)
+[![Build Status](https://travis-ci.org/ncaq/yesod-recaptcha2.svg?branch=master)](https://travis-ci.org/ncaq/yesod-recaptcha2)
 
 [hackage](https://hackage.haskell.org/package/yesod-recaptcha2)
 
diff --git a/src/Yesod/ReCaptcha2.hs b/src/Yesod/ReCaptcha2.hs
--- a/src/Yesod/ReCaptcha2.hs
+++ b/src/Yesod/ReCaptcha2.hs
@@ -3,11 +3,29 @@
 {-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes       #-}
-module Yesod.ReCaptcha2 (YesodReCaptcha(..), reCaptcha, mReCaptcha) where
+{-# LANGUAGE TupleSections     #-}
+module Yesod.ReCaptcha2
+    ( YesodReCaptcha(..)
+      -- * ReCaptcha V2
+    , reCaptcha
+    , mReCaptcha
+      -- * Invisible ReCaptcha
+      -- $invisibleReCaptcha
+    , reCaptchaInvisible
+    , mReCaptchaInvisible
+    , reCaptchaInvisibleForm
+    ) where
 
-import           ClassyPrelude.Yesod
+import           ClassyPrelude
+import           Data.Aeson
 import           Network.HTTP.Simple
 import           Yesod.Auth
+import           Yesod.Core
+import           Yesod.Core.Handler
+import           Yesod.Core.Types
+import           Yesod.Core.Widget
+import           Yesod.Form.Functions
+import           Yesod.Form.Types
 
 -- | default key is testing. you should impl reCaptchaSiteKey and reCaptchaSecretKey
 class YesodAuth site => YesodReCaptcha site where
@@ -15,7 +33,8 @@
     reCaptchaSiteKey = pure "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
     reCaptchaSecretKey :: HandlerFor site Text
     reCaptchaSecretKey = pure "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"
-    -- | with specific language from <https://developers.google.com/recaptcha/docs/language>
+    -- | with specific language from
+    -- <https://developers.google.com/recaptcha/docs/language>
     --
     -- > reCaptchaLanguage = pure (Just "ru")
     reCaptchaLanguage :: HandlerFor site (Maybe Text)
@@ -32,7 +51,9 @@
 reCaptcha = formToAForm mReCaptcha
 
 -- | for Monadic style form
-mReCaptcha :: YesodReCaptcha site => MForm (HandlerFor site) (FormResult (), [FieldView site])
+mReCaptcha
+  :: YesodReCaptcha site =>
+  MForm (HandlerFor site) (FormResult (), [FieldView site])
 mReCaptcha = do
     result <- lift formResult
     return (result, [fieldViewSite])
@@ -43,10 +64,15 @@
                 Just response -> do
                     secret <- reCaptchaSecretKey
                     SiteverifyResponse{success} <- liftIO $ do
-                        req <- parseRequest "POST https://www.google.com/recaptcha/api/siteverify"
+                        req <-
+                          parseRequest
+                          "POST https://www.google.com/recaptcha/api/siteverify"
                         res <- httpJSON $
                             setRequestBodyURLEncoded
-                            [("secret", encodeUtf8 secret), ("response", encodeUtf8 response)] req
+                            [ ("secret", encodeUtf8 secret)
+                            , ("response", encodeUtf8 response)
+                            ]
+                            req
                         return $ getResponseBody res
                     return $ if success
                         then FormSuccess ()
@@ -61,9 +87,72 @@
                       Nothing ->
                         addScriptRemote "https://www.google.com/recaptcha/api.js"
                       Just hl ->
-                        addScriptRemote $ "https://www.google.com/recaptcha/api.js?hl=" <> hl
+                        addScriptRemote $
+                        "https://www.google.com/recaptcha/api.js?hl=" <> hl
                     siteKey <- handlerToWidget reCaptchaSiteKey
                     [whamlet|<div .g-recaptcha data-sitekey=#{siteKey}>|]
             , fvErrors = Nothing
             , fvRequired = True
             }
+
+-- $invisibleReCaptcha
+--
+-- The Invisible ReCaptcha is not as easy as the V2.
+--
+-- 1. Function to check the response: 'reCaptchaInvisible' or 'mReCaptchaInvisible'.
+--
+-- 2. Add the following to the code which creates the form:
+--
+--     > (reCaptchaFormId, reCaptchaWidget, reCaptchaButtonAttributes) <-
+--     > reCaptchaInvisibleForm Nothing
+--
+-- 3. Add the id to the form, class and attributes to the button and the widget somewhere.
+--    Example:
+--
+--     @
+--     \<form \#\#{reCaptchaFormId} method=post action=@{route} enctype=#{enctype}\>
+--       ^{widget}
+--       ^{reCaptchaWidget}
+--
+--       \<button .g-recaptcha *{reCaptchaButtonAttributes}\>
+--         Submit
+--     @
+
+-- | check for Applicative style form
+reCaptchaInvisible :: YesodReCaptcha site => AForm (HandlerFor site) ()
+reCaptchaInvisible = formToAForm ((,[]) <$> mReCaptchaInvisible)
+
+-- | check for Monadic style form
+mReCaptchaInvisible
+  :: YesodReCaptcha site => MForm (HandlerFor site) (FormResult ())
+mReCaptchaInvisible = fst <$> mReCaptcha
+
+-- | generate all required parts (except the check) for a Invisible ReCaptcha
+reCaptchaInvisibleForm
+    :: YesodReCaptcha site
+    => Maybe Text -- ^ The id of the form, a new will be created when 'Nothing' is passed
+    -> Maybe Text
+    -- ^ The javascript to call after a successful captcha,
+    -- it has to submit the form, a simple one will be generated when 'Nothing' is passed
+    -> HandlerFor site (Text, WidgetFor site (), [(Text, Text)])
+reCaptchaInvisibleForm mIdent mScript = do
+    mReCaptchaLanguage <- reCaptchaLanguage
+    siteKey <- reCaptchaSiteKey
+    identForm <- maybe newIdent return mIdent
+    scriptName <- maybe (("reCaptchaOnSubmit_" <>) <$> newIdent) return mScript
+    let
+      widget = do
+        case mReCaptchaLanguage of
+          Nothing ->
+            addScriptRemote "https://www.google.com/recaptcha/api.js"
+          Just hl ->
+            addScriptRemote $ "https://www.google.com/recaptcha/api.js?hl=" <> hl
+        when (isNothing mScript) $
+          toWidgetHead [hamlet|
+<script>function #{scriptName}(token) { document.getElementById("#{identForm}").submit(); }
+|]
+    return
+      ( identForm
+      , widget
+      , [("data-sitekey", siteKey), ("data-callback", scriptName)]
+      )
diff --git a/yesod-recaptcha2.cabal b/yesod-recaptcha2.cabal
--- a/yesod-recaptcha2.cabal
+++ b/yesod-recaptcha2.cabal
@@ -1,11 +1,13 @@
--- This file has been generated from package.yaml by hpack version 0.20.0.
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.31.0.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: d33d7c41317f538fc8619b0117572564e3a742273756bae5f8ae1271aa6f36b4
+-- hash: 2b3e3fe3c6054faefe316aba4920104bb8025b052b3857c3ff5444752b269ae7
 
 name:           yesod-recaptcha2
-version:        0.2.4
+version:        0.3.0
 synopsis:       yesod recaptcha2
 description:    recaptcha2 for yesod-form
 category:       Web
@@ -17,8 +19,6 @@
 license:        MIT
 license-file:   LICENSE
 build-type:     Simple
-cabal-version:  >= 1.10
-
 extra-source-files:
     README.md
 
@@ -30,10 +30,13 @@
   hs-source-dirs:
       src
   build-depends:
-      base >=4.7 && <5
-    , classy-prelude-yesod
+      aeson
+    , base >=4.7 && <5
+    , classy-prelude
     , http-conduit
     , yesod-auth
+    , yesod-core
+    , yesod-form
   exposed-modules:
       Yesod.ReCaptcha2
   other-modules:
