Link to home
Start Free TrialLog in
Avatar of kadin
kadinFlag for United States of America

asked on

How to set cookie for 1 year into the future?

I found this code below. I am having trouble understanding it. I cannot find an understandable explanation for how to set a cookie to expire in the future. In php it's simple:

This is 3 months into the future. How can I do this in javaScript? Thanks.
time() + 60 * 60 * 24 * 90  

var theDate = new Date();
var oneYearLater = new Date( theDate.getTime() + 31536000000 );
var expiryDate = oneYearLater.toGMTString();
Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

This page http://www.w3schools.com/js/js_cookies.asp has demo code for setting all the cookie params in javascript including this code to set a cookie.
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;
} 

Open in new window

Avatar of kadin

ASKER

Thanks. That is one of the first ones I looked at. I don't understand it enough to make anything work.

For example, this alerts nothing.
var d = new Date();
alert(d);

Do I have to house this inside a function to get it to alert?
This alerts:
alert('text');
Avatar of kadin

ASKER

Here is what I have. I can get it to alert today's date, but not tomorrows date.

var thedate = new Date;
thedate.getTime() + (60*60*24);
alert(thedate);
I'm not sure what the 'alert' has to do with anything.  Here is a working example with a long note about using it.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>JS Cookie</title>
<script type="text/javascript">
<!--
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;
} 
// -->
</script>
</head>
<body onload="setCookie('test', '999', 365);">
<h1>JS Cookie</h1>
Note that this must be run from a web server for it to work properly.  Cookies are set by domain and running this from just a file won't have a domain.  In Firefox, you can go to Tools -> Options -> Privacy and select Custom settings so you can see your cookies.  They are listed by domain so you need to know what domain you are on.
</body>
</html>

Open in new window

Note that your thedate.getTime() returns a timestamp in seconds since 1/1/1970.  I've added it to the demo above.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>JS Cookie</title>
<script type="text/javascript">
<!--
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;
} 
// -->
</script>
</head>
<body onload="setCookie('test', '999', 365);">
<h1>JS Cookie</h1>
Note that this must be run from a web server for it to work properly.  Cookies are set by domain and running this from just a file won't have a domain.  In Firefox, you can go to Tools -> Options -> Privacy and select Custom settings so you can see your cookies.  They are listed by domain so you need to know what domain you are on.
<script type="text/javascript">
<!--
var thedate = new Date;
var thedate2 = thedate.getTime() + (60*60*24);
alert('1:'+thedate+'\r\n2: '+thedate2); 
// -->
</script>
</body>
</html>

Open in new window

Avatar of kadin

ASKER

This is what I have so far: It is showing up in my firefox cookies, but when I use php to get cookie value, I get nothing.
if (isset($_COOKIE['value'])) {
	$cookie = $_COOKIE['value'];
}

setCookie('survey', 57, 365, '/', 'www.mysite.com', 'TRUE');

function setCookie(cookieName, value, exDays, path, domain, https) {
  var d = new Date();
  d.setTime(d.getTime() + (exDays*24*60*60*1000));
  var expires = d.toUTCString();
  document.cookie = 'name=' + cookieName;
	document.cookie = 'value=' + value;
	document.cookie = 'expires=' + expires;
	document.cookie = 'path=' + '/';
	document.cookie = 'domain=' + 'www.mysite.com';
	document.cookie = 'secure=' + https;
} 

Open in new window

If you set a cookie with javascript, the cookie will not show up in PHP unless you request the page again.  PHP on the server knows nothing about what happens in the browser after it sends the page.  And since you are setting "https=true", you will only see the cookie if you access the page thru 'https' and not 'http'.

And your PHP is looking for a cookie named 'value' while your javascript is setting one named 'survey'.

http://php.net/manual/en/reserved.variables.cookies.php
Avatar of kadin

ASKER

I am using AJAX to send form data to a php page. The php page first checks for a cookie:

if (isset($_COOKIE['name']) && $_COOKIE['name'] != '') {
	echo '<error>Our records indicate you have already responded to this survey.</error>';
}

Open in new window


XML is sent back to javaScript. If no echo <error> then javaScript sets a cookie. I then refresh the page and fill out the form again. AJAX sends form data back to php page and if(isset($_COOKIE)) is checked again. At this point I expect php to echo back to javaScript an <error> indicating the visiter has already taken the survey. but it doesn't., php continues on to process the survey again. I check the cookie and verify it is in the firefox browser.

I refresh the page and isset($_COOKIE['name']) detects nothing. I try survey or value and I get nothing.
I am using https, that is why I set it to TRUE.

Firefox is showing no javaScript errors in the console. And no php errors.

One thing to note: I do not know what exactly the cookie in the browser should look like and read. I already have a session id sitting there and I don't know if that interferes with this new javaScript generated cookie.

In addition to that, the visitor might take 100 or more surveys. Does that mean 100 or more cookies?
 
Firefox cookie.
User generated image
Cookies with different names do not 'interfere' with each other.  Setting a cookie with the same name overwrites the previous one with that name.  In your image above, you have a cookie set for 'name'.  Make sure it has a value when you set it.

You also have cookies set with the names of 'value', 'expires', 'path', 'domain', 'secure', and 'PHPSESSID'.  Those are Names of cookies, not the parameters.  Each of those cookies will have those parameters and you can see them when you click on one of those cookies and look at the detail info at the bottom of the window.  

Note that when a cookie is returned with a page request, Only the name and the value are returned, nothing else.  The server can not get the expiration of a cookie that has been set.  You can see it in the Firefox Cookie window.

I use a Firefox add-on called Live HTTP headers 0.17 to view the HTTP request and response headers.  You can see the cookie being sent to the server with that add-on but since you are setting the cookie with javascript, you will not see it being set.
One other thing that may be important.  The javascript to set the cookie must run before the AJAX that is supposed to report it.  If the AJAX runs before the cookie is set, there won't be any cookie to send.
Avatar of kadin

ASKER

The cookie is showing in the browser there fore AJAX must not be interfering with it. The problem must be in the names. The code below may be wrong.

setCookie('survey', '57', 365, '/', 'www.mysite.com', 'TRUE');

function setCookie(cookieName, value, exDays, path, domain, https) {
  var d = new Date();
  d.setTime(d.getTime() + (exDays*24*60*60*1000));
  var expires = d.toUTCString();
	document.cookie = 'name=' + cookieName; + 'value=' + value; + 'expires=' + expires; + 'path=' + path; + 'domain=' + domain; + 'secure=' + https;
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of kadin

ASKER

I am using camel case in all my javaScript and not had a problem. I changed exDays to exdays just in case.
Here is what I have. It is still not working.

document.cookie = cookieName + '=' + value + ';' + expires + '; path=' + path + '; domain=' + domain + ';' + https + ';';

Open in new window


Now I get one cookie.
User generated image
Avatar of kadin

ASKER

I take that back. It is working now. I had to change

if (isset($_COOKIE['name']) && $_COOKIE['name'] != '')      

to:

if (isset($_COOKIE['survey']) && $_COOKIE['survey'] != '')

I noticed the cookie expires: At end of session  -  in the image of browser cookies above,  and shows no future date.
Clearly you did not do what I suggested and run my demo code with only changing the domain because I already know that it works on a 'https' domain.
User generated image
Avatar of kadin

ASKER

Respectfully; the code you gave me above can't work as is. It is a mix of both yours and my code. For example, the word Secure must be changed to https.

I see a difference your probably leading to is this line:
var expires = "expires="+d.toUTCString();

Your right that I did miss this line. The code is now leaving a date in the cookie.
Avatar of kadin

ASKER

What I still don't understand is why 1000? I see 60seconds * 60minutes * 24hours * 365 days.

d.setTime(d.getTime() + (exdays*24*60*60*1000));
Avatar of kadin

ASKER

I just noticed your cookie says encrypted connections only and mine says for any connections. I see no difference in the way you wrote these: www.dibsiam.com

One for 'dibsiam.com', one for 'www.dibsiam.com' and another for 'www.dibsiam.com' over an encrypted connection.
the word Secure must be changed to https
No.  According to Mozilla and IETF, 'Secure' is the correct term.  http://www.ietf.org/rfc/rfc2965.txt   See section 3.2.2.

'1000' because a javascript 'timestamp' is in milliseconds, not seconds.

Apparently Firefox decided that there were only two cookies, one for 'dibsiam.com' and one for 'www.dibsiam.com' over an encrypted connection.   I had to open and re-open the Tools and view the cookies because they didn't seem to 'take' at first.
Another reason to use my demo code is that the cookie string is written to the screen so you can see it when it is set.
Avatar of kadin

ASKER

That 'Secure' did the trick. Now it shows the encrypted.

What is your opinion? A visitor at my site in the future may fill out many surveys, perhaps a 100. That will leave 100 cookies in their browser. I notice other sites leave less than 20. Is 100 acceptable or rude?
The biggest limit on cookies is space.  This is a fairly good general article on cookies that include info on size:  http://www.nczonline.net/blog/2009/05/05/http-cookies-explained/   See the section titled Cookie restrictions  It says that the limit on the number of cookies can be as low as 30 for a single domain.  However... there are ways to put more data in a single cookie.  They're suggesting name/value pairs like you would see in a query string.  You can also pipe-delimit the data like 'survey=12|34|96|733".  If you do that, you have to read the cookie and append the new data to the old data.
Avatar of kadin

ASKER

That is a very informative article. I will have to read the rest of it tomorrow. Pipe-delimiting cookie data is good to know. I just had a thought. When the cookie expires, all the pipe-delimited data will be deleted if I am not mistaken. In my case each number represents a survey taken on a particular date. I am preparing for the possibility someone might take 30 surveys in a day.

Cookies may not be a solution for my site. From what I have researched there doesn't seem to be a very practical solution for limiting a site visitor to taking a particular survey just once.
Since you are sending it to a PHP page, I would collect the info in a database.  That way the cookie only has to represent one thing at a time.
Avatar of kadin

ASKER

I don't understand, which info would you collect into a database? Are you implying the site visitor should be logged in?
I thought you were putting some kind of survey info in the cookie.  Anything that can be put in the cookie can be put in the database.  You can keep track of which visitor by setting a separate long term cookie with the visitor ID on the first visit.  I suggest using a database because you are unlikely to be able to set 100 separate cookies.
Avatar of kadin

ASKER

The system I had set up was to make the visitor login before they could take a survey so I could prevent the visitor from taking any survey more than once. The down side to that is not every visitor wants to register an account and login to take a survey, so the number of survey responses might be lower. Would your suggestion require the visitor to register and login? I am not exactly sure what you mean by visitor id.

And by the way, thanks for all of your help.
You're welcome.  'visitor id' can be any unique id that you want.  It's just a means of correlating the surveys to the survey taker.  If you already have a login for them, that would be the 'id' that I would use.  Otherwise, if they go to the survey page and do not have a cookie set for your site, you can assign them some 'id' and put it in a cookie on their first visit.
Avatar of kadin

ASKER

Otherwise, if they go to the survey page and do not have a cookie set for your site, you can assign them some 'id' and put it in a cookie on their first visit.

By this, do you mean, (upon cookie creation for a non-registered visitor), store cookie visitor id, survey no. and expiration date in the database? That way solving the expiration date problem when the browser deletes the cookie that holds all the pipe-delimited survey numbers the non-registered visitor has taken (35|57|221|355) etc.
Yes, that's what I would do.  It's not a perfect solution because people seem to find ways to delete their cookies but it avoid having to create 100 cookies which will be over the limit for a domain.
Avatar of kadin

ASKER

Thanks for your advice. I will think it over and decide what I am going to do.