I'm using TypeForm to handle my lead generation forms. The form I'm using has been embedded on the home page of my site. This embedding creates an iframe showing the popup every time the home page is loaded, even if the 'X' is clicked.
Having contacted TypeForm, I have been told that I would need to set a cookie to prevent the popup loading each time. In fact their reply was "To ensure the Typeform only appears once you will have to add cookies to your site in order to ensure a user only sees it one time. This isn't a feature we currently have but hopefully with more requests it's something we could add!"
Embed Code:
<a class="typeform-share button" href="https://example.typeform.com/to/fbPnzs" data-mode="drawer_left" data-auto-open=true target="_blank" style="display:none;"></a>
<script>
(function() {
var qs, js, q, s, d = document,
gi = d.getElementById,
ce = d.createElement,
gt = d.getElementsByTagName,
id = "typef_orm_share",
b = "https://embed.typeform.com/";
if (!gi.call(d, id)) {
js = ce.call(d, "script");
js.id = id;
js.src = b + "embed.js";
q = gt.call(d, "script")[0];
q.parentNode.insertBefore(js, q)
}
})()
</script>
The embed URL is example.typeform.com whereas the website where the form is to be embedded is not the same. Does consideration need to be made about same-origin?
What do I need to implement in terms of code to the functions.php file of my WordPress site to add a cookie that allows the popup to show only once and/or never show again if the 'X' is clicked?
Thank to Nicolas for his answer!
Having checked over the SDK, I've adapted Nicolas' snippet to cater to the left draw popup. This checks if a cookie exists, if it does not, it should set it and display the left draw TypeForm popup; if the cookie does exist, it won't show.
var url = "https://demo.typeform.com/to/njdbt5" // Update with your TypeForm URL
let params = new URLSearchParams( location.search );
url += "?utm_source=" + params.get( 'utm_source' ); // Replace with the hidden values you want to pass
var displayed = getCookie( "typeform_displayed" ); // Check for the cookie typeform_displayed
if ( displayed ) {
null
} else if ( !displayed && displayed === "" ) {
setCookie( "typeform_displayed", true, 365 ); // Set typeform_displayed cookie with a value of true and an expiry of 365 days
showEmbed();
}
//
function showEmbed() {
window.typeformEmbed.makePopup( url, {
mode: 'drawer_left',
autoOpen: true,
hideHeaders: true,
hideFooters: true,
} )
}
// Cookie Manipulation
// Source: https://www.w3schools.com/js/js_cookies.asp
function setCookie( cname, cvalue, exdays ) {
var d = new Date();
d.setTime( d.getTime() + ( exdays * 24 * 60 * 60 * 1000 ) );
var expires = "expires=" + d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
function getCookie( cname ) {
var name = cname + "=";
var decodedCookie = decodeURIComponent( document.cookie );
var ca = decodedCookie.split( ';' );
for ( var i = 0; i < ca.length; i++ ) {
var c = ca[ i ];
while ( c.charAt( 0 ) == ' ' ) {
c = c.substring( 1 );
}
if ( c.indexOf( name ) == 0 ) {
return c.substring( name.length, c.length );
}
}
return "";
}
I think this is totally doable using Typeform Embed SDK.
You will need to check if the cookie is already set. And depending on the value display or not the embed typeform.
I made a working example on Glitch, you can look at it here.
In code the logic would look like this:
var displayed = getCookie("displayed_typeform");
if (displayed){
embedElement.innerHTML="<h2>Typeform already displayed once.</h2>"
} else if (!displayed && displayed === "") {
setCookie("displayed_typeform", true, 365);
showEmbed();
}
Hope it helps :)
Related
I have this bit of code below that essentially on click of an a tag copies the text of an input field to the clipboard and then opens a new tab where the user pastes the text.
This all works completely fine UNTIL the cookie is set. I have tried it with testing 10 of the different a tags before the cookie is set.
Once the cookie is set, the new tab will still open, the input field I am copying the text from still updates, but if I paste into notepad or the window that opens, it will be whatever was copied last and not the most up to date. If I remove the cookie and reload everything goes back to how it should function.
So I am not sure why the cookie being set would stop the clipboard from updating.
//Set Cookie Function
function setCookie(cname, cvalue, exdays) {
const d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
let expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
//Get Cookie Function
function getCookie(name) {
var dc = document.cookie;
var prefix = name + "=";
var begin = dc.indexOf("; " + prefix);
if (begin == -1) {
begin = dc.indexOf(prefix);
if (begin != 0) return null;
}
else
{
begin += 2;
var end = document.cookie.indexOf(";", begin);
if (end == -1) {
end = dc.length;
}
}
// because unescape has been deprecated, replaced with decodeURI
//return unescape(dc.substring(begin + prefix.length, end));
return decodeURI(dc.substring(begin + prefix.length, end));
}
$(document).on('click', '.pop-top ul li a', function() {
var copiedRole = $(this);
$('#copyText').val(copiedRole.text());
navigator.clipboard.writeText($('#copyText').val());
var acknowledgeExists = getCookie("acknowledge");
if(acknowledgeExists == null) {
$('#copyMessage, .frosted').addClass('show');
} else {
window.open('[redacted]', '_blank');
}
});
//Create Cookies
$("#acknowledge").on('click', function() {
$('#copyMessage, .frosted').removeClass('show');
window.open('[redacted]', '_blank');
if($('#never').is(':checked')) {
setCookie("acknowledge", "yes", 1);
}
});
So it turns out that it was not the cookie, but the window.open firing immediately. MDN docs for the clipboard API note that the tab must be active. So even though my code has the write to clipboard function before the cookie check, it still would fire quick enough to prevent it.
While not an ideal solution wrapping the window.open in the cookie if/else in a setTimeout for 1 second works fine.
I made this little code using JS to disable cookies:
$(document).ready(function() {
var cookie_settings = getCookie("cookie-settings"); //Main cookie which contains cookie preferences
var cookie_selector = document.getElementById("cookie-selector"); //Modal for cookie selection
var g_recaptcha = document.getElementById("cookie-g-recaptcha"); //Example checkbox cookie
var g_tag_manager = document.getElementById("cookie-g-tag-manager"); //Example checkbox cookie
var messenger_plugin = document.getElementById("cookie-fb-mccp"); //Example checkbox cookie
var g_analytics = document.getElementById("cookie-g-analytics"); //Example checkbox cookie
var cookie_set = document.getElementById("cookie-set"); //Button to save preferences
if (cookie_settings == null) { //Check if main cookie exist
$(cookie_selector).modal({
backdrop: 'static',
keyboard: false
}); //If not exist, open cookie selector modal
} else {
var cookie_settings_raw_values = getCookie("cookie-settings"); //read and save main cookie in var
var cookie_settings_values = cookie_settings_raw_values.split('&'); //save main cookie content in array
if (cookie_settings_values.includes(g_recaptcha.id)) {
//If array contains recaptcha example include it
//for example append in head -> $('head').append('myscript');
}
if (cookie_settings_values.includes(g_tag_manager.id)) {
//same
//for example append in head -> $('head').append('myscript');
}
if (cookie_settings_values.includes(messenger_plugin.id)) {
//same
//for example append in head -> $('head').append('myscript');
}
if (cookie_settings_values.includes(g_analytics.id)) {
//same
//for example append in head -> $('head').append('myscript');
}
//or you can remove else condition and manage this part from php
}
$(cookie_set).click(function() { //on save preferences click
var selected_cookies = [g_recaptcha.id, g_tag_manager.id]; //make array and include required cookies
if (messenger_plugin.checked == true) {
//if messenger plugin example checkbox is checked push it's reference in array
selected_cookies.push(messenger_plugin.id);
}
if (g_analytics.checked == true) {
//same for the other optional checkboxes
selected_cookies.push(g_analytics.id);
}
var expiry_date = new Date();
expiry_date.setMonth(expiry_date.getMonth() + 6); //expiration date 6 months in my case, you can set what you want
document.cookie = document.cookie = "cookie-settings=" + selected_cookies.join('&') + "; expires=" + expiry_date.toGMTString(); //make main cookie with required and optional selected checkboxes (the deadline is 6 months after the creation of the cookie)
location.reload(); //reload page
});
//get cookie by name
function getCookie(name) {
var document_cookie = document.cookie;
var prefix = name + "=";
var begin = document_cookie.indexOf("; " + prefix);
if (begin == -1) {
begin = document_cookie.indexOf(prefix);
if (begin != 0) {
return null;
}
} else {
begin += 2;
var end = document.cookie.indexOf(";", begin);
if (end == -1) {
end = document_cookie.length;
}
}
return decodeURI(document_cookie.substring(begin + prefix.length, end));
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
My question is it enough to disable third-party cookies?
Not including the scripts if the user does not accept cookies, do the stored ones become useless? Does the site comply with the GDPR?
If not, do you have any other valid alternative to propose that is not the use of third party codes?
Most of the websites, which are trying to be GDPR compliant are not loading any of these scripts by default (as you probably do). First they show a popup, if a user wants to load e.g. tracking cookies and if the user agrees they will be loaded. The configured setting which services should be loaded / what the user has selected will then be stored either in a cookie or e.g. the localStorage.
So yes, your site seems to be GDPR compliant when we take a look at the approach how you load the external scripts.
If you’re talking about deleting them, set it again with the expiry date before today.
I have a countdown clock here that resets when the page is refreshed. I would appreciate it if someone could help me?
I have included the script below.
<script type="text/javascript">
var ticker = function() {
$("#ticker").css({
left: "120%"
}).animate({
left: "-420px"
}, 6000, 'linear', ticker);
}
ticker();
</script>
Considering you need it to be "running" while user is not in the page, I will point out that Javascript is a client side scripting language Javascript code is run in local side i.e its interpereted by the browser. This makes hard to "keep" track of things if the user refreshes the page until unless you have have stored them somewhere. There can be different approaches for your solution such as:-
LocalStorage
Cookies
Server Side Clock
You can use either of the three. You can use localstorage to save the clock end time and whenever the user refreshes the page get the value from localstorage and start you clock accordingly. Similar approach can be used with cookies. Or you can use some server side code to initialize the clock whenever your page loads the server will set start the clock accordingly. but there can be some lag as mentioned above in comments. So the best approach in my opinion, if you just want to use javascript, would be to use cookies/localstorage to save the exact time when the countdown will reach value 0. So everytime you load into the page, you can get the stored value , and get how long is missing yet and set the clock accordingly.
Some coding
Create a cookie with expiration time:
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
Get a cookie:
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
Sample of use:
function checkCookie() {
var clock = getCookie("clock");
if (clock != "") {
//You already have the cookie. Make use of it
} else {
//You still dont have the cookie, create new clock, and save cookie
//i.e.
setCookie("clock", new Date().getTime().toString(), 365);
}
}
I realize that FireFox, Chrome, Safari, & Opera can limit the number of cookies a domain/website can set. So I thought of a different approach to storing my web forms many text, radio buttons, and select box values -Set a multi-variable cookie for each major section of the web form, instead of a separate cookie for each variable.
It would look something like this (inside each cookies content)...
firstName=John;&&;lastName=Andrews;&&;streetAddress=1234 Memory Ln.
What I'm looking for is a JavaScript function that will create/update this type of cookie on-the-fly properly (using element names instead of ID's for max compatibility with radio buttons) , triggered on each form elements 'onchange' event.
Then when needed, a function to load the cookie into a JavaScript string variable, parse the string for actual variables from between ';&&;' and load them into real JavaScript variables by the corresponding name, then when the user returns to the form the JavaScript fills in the values of the corresponding (by same name) form elements with these values, automatically.
Any help would be greatly appreciated.
Thanks in Advance!!
-James A.
FULL SOLUTION BELOW : Here is the complete 'save_form.js' code!
//<!-- Prerequisites: jquery.min.js -->
//<!-- A script to set a cookie [Argument(s) accepted: Cookie Name, Cookie Value, etc.] [BEGIN] -->
function set_cookie ( name, value, path, domain, secure )
{
var cookie_string = name + "=" + escape ( value );
var cookie_date = new Date(); // current date & time ;
var cookie_date_num = cookie_date.getTime(); // convert cookie_date to milliseconds ;
cookie_date_num += 35 * 60 * 1000; // add 35 minutes in milliseconds ;
cookie_date.setTime(cookie_date_num); // set my_date Date object 35 minutes forward ;
cookie_string += "; expires=" + cookie_date.toGMTString();
if ( path )
cookie_string += "; path=" + escape ( path );
if ( domain )
cookie_string += "; domain=" + escape ( domain );
if ( secure )
cookie_string += "; secure";
document.cookie = cookie_string;
};
//<!-- A script to set a cookie [Argument(s) accepted: Cookie Name, Cookie Value, etc.] [END] -->
//<!-- A script to grab a cookies value by name [Argument(s) accepted: Cookies Name] [BEGIN] -->
function get_cookie ( cookie_name )
{
var results = document.cookie.match ( '(^|;) ?' + cookie_name + '=([^;]*)(;|$)' );
if ( results )
{
return ( unescape ( results[2] ) );
}
else
{
return null;
};
};
//<!-- A script to grab a cookies value by name [Argument(s) accepted: Cookies Name] [END] -->
function populateCookieFromForm ( cookieName ) {
var encodedCookie;
var preCookieObj = '{';
var allMainElements = $('form').find('input[type=text], select');
for (var i=0; i < allMainElements.length; i++)
{
preCookieObj = preCookieObj + '"' + allMainElements[i].name +'":"'+ allMainElements[i].value +'",';
};
preCookieObj = preCookieObj.substring(0, preCookieObj.length - 1);
preCookieObj = preCookieObj + '}';
//<!-- btoa() encodes 'string' argument into Base64 encoding -->
encodedCookie = btoa( preCookieObj );
set_cookie(cookieName, encodedCookie);
};
function populateFormFromCookie (cookieName) {
if ( ! get_cookie ( cookieName ) )
{
//<!-- Do Nothing - No Cookie For this form set. -->
}
else
{
//<!-- atob() decodes 'string' argument from Base64 encoding -->
jSONCookieObj = atob( get_cookie ( cookieName ) ) ;
jSONObj = JSON.parse( jSONCookieObj );
var allMainElements = $('form').find('input[type=text], select');
for (var i=0; i < allMainElements.length; i++)
{
var elementName = allMainElements[i].name;
var elementValue = jSONObj[elementName];
allMainElements[i].value = elementValue;
};
};
};
function populateCookieFromRadios (cookieName) {
var radioState={};
$(':radio').each(function(){
if(!radioState[this.name]){
radioState[this.name]={};
}
radioState[this.name][this.value]=this.checked;
});
/* stringify to JSON and convert to Base64 */
var storeString= btoa(JSON.stringify(radioState));
/* store in cookie*/
set_cookie(cookieName, storeString);
};
function populateRadiosFromCookie (cookieName) {
if ( ! get_cookie ( cookieName ) )
{
//<!-- Do Nothing - No Cookie For this form set. -->
}
else
{
var cookieString = get_cookie ( cookieName );
var newPageState= JSON.parse(atob(cookieString));
/* loop through radios setting state */
$(':radio').prop('checked',function(){
return newPageState[this.name][this.value];
});
};
};
This is how you properly call these functions. Near the bottom of the HTML/PHP page containing the form, place this JavaScript respectively:
<script type="text/javascript">
//<!-- If returning user detected, populate form with cookie values [BEGIN] -->
populateFormFromCookie('thisForm');
populateRadiosFromCookie('thisFormRadios');
//<!-- If returning user detected, populate form with 'section' cookie values [END] -->
//<!-- On change of ALL form elements re-save form cookie(s) [BEGIN] -->
$('input[type=radio]', $('form')).on('change',function(e){
populateCookieFromRadios('thisFormRadios');
});
$('input[type=text], select, textarea', $('form')).on('change',function(e){
populateCookieFromForm('thisForm');
});
$('input[type=text]', $('form')).on('input',function(e){
populateCookieFromForm('thisForm');
});
//<!-- On change of ALL form elements re-save form cookie(s) [END] -->
</script>
The next task is to see if all of this can be done without jQuery...hmm...
Just a day ago I posted this question and found/built my own solution, for lack of a sufficient answer. Now, I need help going through a similar process again. This time, however, I need to capture (save to cookie as 'Base64' data) and recall (recheck upon user return) the state of all the radio button groups (by 'name' not 'ID', for obvious reasons), after the page loads, and if need be trigger all corresponding onchange events attached to them. For example, if a radio button group label has the question, "Have you lived at this address for more than 3 years?' one radio button label says 'Yes', and the other, 'No'. If the user chooses 'No' an extra 'address' table row is displayed in the table. All of the mechanics of the table appearing on 'No' 'checked' has already been done. I'm looking for a simple way to:
A:) Record all radio button group(s) state(s) (i.e which one is checked), on the 'onchange' event of any radio button on the form.
B:) Convert that information to JSON or some other record keeping
C:) Base64 encode data in step [B:]
D:) Save to a cookie
Upon page reload (user returns to page)...
E:) Grab data from cookie
F:) Decode Base64 and assign to variable
G:) From data iterate through all the forms radio buttons re-checking what was originally checked.
Sound easy? Give it a try! I did....and am still.
Here's the basics in jQuery without the cookie saving, will leave that to you
var radioState={};
$(':radio').each(function(){
if(!radioState[this.name]){
radioState[this.name]={};
}
radioState[this.name][this.value]=this.checked
});
/* stringify to JSOn and convert to Base64 */
var storeString= btoa(JSON.stringify(radioState));
/* store in cookie*/
/* on page load pull data from cookie (if exists) - add a cookie validation test*/
var cookieString=storeString;// just using this for demo
var newPageState= JSON.parse(atob(cookieString));
/* loop through radios setting state */
$(':radio').prop('checked',function(){
return newPageState[this.name][this.value];
});
DEMO
atob() and btoa() docs
EDIT: Use localStorage if browser supported, with cookie fallback. Will minimize cookie size sent to server for each and every http request made to site
Thank You #Charlietfl. +1! Here is the complete 'save_form.js' code!
//<!-- Prerequisites: jquery.min.js -->
//<!-- A script to set a cookie [Argument(s) accepted: Cookie Name, Cookie Value, etc.] [BEGIN] -->
function set_cookie ( name, value, path, domain, secure )
{
var cookie_string = name + "=" + escape ( value );
var cookie_date = new Date(); // current date & time ;
var cookie_date_num = cookie_date.getTime(); // convert cookie_date to milliseconds ;
cookie_date_num += 35 * 60 * 1000; // add 35 minutes in milliseconds ;
cookie_date.setTime(cookie_date_num); // set my_date Date object 35 minutes forward ;
cookie_string += "; expires=" + cookie_date.toGMTString();
if ( path )
cookie_string += "; path=" + escape ( path );
if ( domain )
cookie_string += "; domain=" + escape ( domain );
if ( secure )
cookie_string += "; secure";
document.cookie = cookie_string;
};
//<!-- A script to set a cookie [Argument(s) accepted: Cookie Name, Cookie Value, etc.] [END] -->
//<!-- A script to grab a cookies value by name [Argument(s) accepted: Cookies Name] [BEGIN] -->
function get_cookie ( cookie_name )
{
var results = document.cookie.match ( '(^|;) ?' + cookie_name + '=([^;]*)(;|$)' );
if ( results )
{
return ( unescape ( results[2] ) );
}
else
{
return null;
};
};
//<!-- A script to grab a cookies value by name [Argument(s) accepted: Cookies Name] [END] -->
function populateCookieFromForm ( cookieName ) {
var encodedCookie;
var preCookieObj = '{';
var allMainElements = $('form').find('input[type=text], select');
for (var i=0; i < allMainElements.length; i++)
{
preCookieObj = preCookieObj + '"' + allMainElements[i].name +'":"'+ allMainElements[i].value +'",';
};
preCookieObj = preCookieObj.substring(0, preCookieObj.length - 1);
preCookieObj = preCookieObj + '}';
//<!-- btoa() encodes 'string' argument into Base64 encoding -->
encodedCookie = btoa( preCookieObj );
set_cookie(cookieName, encodedCookie);
};
function populateFormFromCookie (cookieName) {
if ( ! get_cookie ( cookieName ) )
{
//<!-- Do Nothing - No Cookie For this form set. -->
}
else
{
//<!-- atob() decodes 'string' argument from Base64 encoding -->
jSONCookieObj = atob( get_cookie ( cookieName ) ) ;
jSONObj = JSON.parse( jSONCookieObj );
var allMainElements = $('form').find('input[type=text], select');
for (var i=0; i < allMainElements.length; i++)
{
var elementName = allMainElements[i].name;
var elementValue = jSONObj[elementName];
allMainElements[i].value = elementValue;
};
};
};
function populateCookieFromRadios (cookieName) {
var radioState={};
$(':radio').each(function(){
if(!radioState[this.name]){
radioState[this.name]={};
}
radioState[this.name][this.value]=this.checked;
});
/* stringify to JSON and convert to Base64 */
var storeString= btoa(JSON.stringify(radioState));
/* store in cookie*/
set_cookie(cookieName, storeString);
};
function populateRadiosFromCookie (cookieName) {
if ( ! get_cookie ( cookieName ) )
{
//<!-- Do Nothing - No Cookie For this form set. -->
}
else
{
var cookieString = get_cookie ( cookieName );
var newPageState= JSON.parse(atob(cookieString));
/* loop through radios setting state */
$(':radio').prop('checked',function(){
return newPageState[this.name][this.value];
});
};
};
This is how you properly call these functions. Near the bottom of the HTML/PHP page containing the form, place this JavaScript respectively:
<script type="text/javascript">
//<!-- If returning user detected, populate form with cookie values [BEGIN] -->
populateFormFromCookie('thisForm');
populateRadiosFromCookie('thisFormRadios');
//<!-- If returning user detected, populate form with 'section' cookie values [END] -->
//<!-- On change of ALL form elements re-save form cookie(s) [BEGIN] -->
$('input[type=radio]', $('form')).on('change',function(e){
populateCookieFromRadios('thisFormRadios');
});
$('input[type=text], select, textarea', $('form')).on('change',function(e){
populateCookieFromForm('thisForm');
});
$('input[type=text]', $('form')).on('input',function(e){
populateCookieFromForm('thisForm');
});
//<!-- On change of ALL form elements re-save form cookie(s) [END] -->
</script>
The next task is to see if all of this can be done without jQuery...hmm...