<p>First, you want to always set the cookie to update it to the current date. Otherwise, the user will see content marked as new repeatedly. Also, setting <code>'now'</code> as a string won't work – how will you know when <code>'now'</code> is later on? Finally, make sure to use proper names to make your code easier to parse.</p>
<pre><code>{# Add other parameters to the query here. #}
{% set entriesQuery = craft.entries() %}

{# Only show entries since the last visit if the user has visited before. #}
{% set last_visit = getCookie('last_visit') %}
{% if last_visit %}
    {% set last_visit_date = last_visit|date('Y-m-d') %}
    {% do entriesQuery.postDate(&quot;&gt; #{last_visit_date}&quot;) %}
{% endif %}
{% set newEntries = entriesQuery.all() %}
</code></pre>
<p>This will find all available content if the user hasn't visited before, and only entries added after the last visit (according to the timestamp) if the user has visited before.</p>
<p>Finally, always update the <code>last_visit</code> cookie to store the current time, regardless of whether the user has visited the site before:</p>
<pre><code>{% do setCookie('last_visit', now | atom, now | date_modify('+1 year') %}
</code></pre>
<p>Note the difference between <code>'now'</code> and <code>now</code>. The latter is a <a href="https://craftcms.com/docs/3.x/dev/global-variables.html#now" rel="noreferrer">global variable containing a <code>DateTime</code> object with the current time</a>. The <a href="https://craftcms.com/docs/3.x/dev/filters.html#atom" rel="noreferrer">atom filter</a> converts that to ISO-8601 for storage (you could also just store the timestamp or <code>Y-m-d</code>, not sure how picky the <code>postDate</code> parameter is). Finally, the third parameter makes sure the cookie will be stored for one year (you can increase that limit, obviously).</p>
<p>Add more parameters (path, domain) as needed. You may want to use secure=true and sameSite=none to allow this cookie to be sent on cross-origin requests as it's not security-related. See <a href="https://web.dev/samesite-cookies-explained/" rel="noreferrer">SameSite cookies explained</a>.</p>
<h3>Without a plugin</h3>
<p>You can also accomplish this without a plugin, though it does get a bit more verbose:</p>
<pre><code>{# Set a cookie using the Response object #}
{% set lastVisitCookie = create({
    class: 'yii\\web\\cookie',
    name: 'last_visit',
    value: now | atom,
}) %}
{% do craft.app.response.cookies.add(lastVisitCookie) %}

{# Read the existing cookie, if any #}
{% set last_visit_cookie = craft.app.request.cookies.get('last_visit') %}
{% set last_visit = last_visit_cookie ? last_visit_cookie.value : null %}
</code></pre>
<h3>Sidenote: Logged-in users</h3>
<p>If your users are logged in, you can also use the <a href="https://craftcms.com/docs/3.x/users.html#lastlogindate" rel="noreferrer"><code>lastLoginDate</code> property</a> of their user account to display new content. A bit more reliable than cookies since it's stored in the database and won't disappear when the visitor clears their cache.</p>

CC BY-SA 4.0
2021-08-21T01:46:38.013Z
Thanks for the extremely thorough reply!! Super helpful. Your sidenote is actually the solution I've gone for -- not sure how I didn't think to do something like that. But I will use the cookie part on another project too. Thanks!
supazu
CC BY-SA 4.0
2021-08-20T08:35:12.493Z
2021-08-20T08:48:14.270Z
2021-08-20T08:48:14.270Z
MoritzLost
<p>I would like to show new content to users since their last visit, and a bit confused about the best approach. I'm thinking I should use the <a href="https://nystudio107.com/docs/cookies/" rel="nofollow noreferrer">Cookies</a> plugin and something like this:</p>
<pre><code>{% if not getSecureCookie('now') %}
  {% do setSecureCookie('now', 'now', now|date) %}
{% endif %}

~~

{% if entry.postDate &gt; now %}
 New Content
{% endif %}
</code></pre>
<p>I understand this is wrong, but just looking for some guidance. How do I set a cookie for now and then check it on the next visit, and only show the new content? Any help much appreciated!</p>

<cookies>
Show content since last visit
# Show content since last visit

(Asked by: username_0 on 2021-08-20)

I would like to show new content to users since their last visit, and a bit confused about the best approach. I'm thinking I should use the Cookies plugin and something like this:
{% if not getSecureCookie('now') %}
  {% do setSecureCookie('now', 'now', now|date) %}
{% endif %}

~~

{% if entry.postDate > now %}
 New Content
{% endif %}

I understand this is wrong, but just looking for some guidance. How do I set a cookie for now and then check it on the next visit, and only show the new content? Any help much appreciated!

**Tags:** cookies

---

## 1 answers

### Answer by username_1 on 2021-08-20. Score: 5 | Accepted answer

First, you want to always set the cookie to update it to the current date. Otherwise, the user will see content marked as new repeatedly. Also, setting 'now' as a string won't work – how will you know when 'now' is later on? Finally, make sure to use proper names to make your code easier to parse.
{# Add other parameters to the query here. #}
{% set entriesQuery = craft.entries() %}

{# Only show entries since the last visit if the user has visited before. #}
{% set last_visit = getCookie('last_visit') %}
{% if last_visit %}
    {% set last_visit_date = last_visit|date('Y-m-d') %}
    {% do entriesQuery.postDate("> #{last_visit_date}") %}
{% endif %}
{% set newEntries = entriesQuery.all() %}

This will find all available content if the user hasn't visited before, and only entries added after the last visit (according to the timestamp) if the user has visited before.
Finally, always update the last_visit cookie to store the current time, regardless of whether the user has visited the site before:
{% do setCookie('last_visit', now | atom, now | date_modify('+1 year') %}

Note the difference between 'now' and now. The latter is a global variable containing a DateTime object with the current time. The atom filter converts that to ISO-8601 for storage (you could also just store the timestamp or Y-m-d, not sure how picky the postDate parameter is). Finally, the third parameter makes sure the cookie will be stored for one year (you can increase that limit, obviously).
Add more parameters (path, domain) as needed. You may want to use secure=true and sameSite=none to allow this cookie to be sent on cross-origin requests as it's not security-related. See SameSite cookies explained.
Without a plugin
You can also accomplish this without a plugin, though it does get a bit more verbose:
{# Set a cookie using the Response object #}
{% set lastVisitCookie = create({
    class: 'yii\\web\\cookie',
    name: 'last_visit',
    value: now | atom,
}) %}
{% do craft.app.response.cookies.add(lastVisitCookie) %}

{# Read the existing cookie, if any #}
{% set last_visit_cookie = craft.app.request.cookies.get('last_visit') %}
{% set last_visit = last_visit_cookie ? last_visit_cookie.value : null %}

Sidenote: Logged-in users
If your users are logged in, you can also use the lastLoginDate property of their user account to display new content. A bit more reliable than cookies since it's stored in the database and won't disappear when the visitor clears their cache.

> **Comments:**
> **username_0**: Thanks for the extremely thorough reply!! Super helpful. Your sidenote is actually the solution I've gone for -- not sure how I didn't think to do something like that. But I will use the cookie part on another project too. Thanks!  

---

