Alternative to Dynamic Cookie Names

Continued from https://www.sitepoint.com/community/t/dynamic-cookie-names/302641/55.

Consider an alternative approach:
Instead of all this dynamic querying, do an anti-3NF approach to your cookie.

When a user signs up, assign a cookie shown_offer to them that contains "0" (and never have an offer 0. You’ll see why in a second.)

When is shown an offer (or closes the offer, whatever), append ","+offerid to their cookie.

Look up a valid offer for the user by first taking the value of shown_offer, splitting it on ,, sanitizing it ($sanitized = implode(",",array_map(intval,explode(",",$cookiestring)) and then querying for the things they HAVEN’T been shown:

  SELECT *
    FROM `offers`
   WHERE `isActive` = 1
   AND `offer_id` NOT IN(".$sanitized.")
   ORDER BY `offer_id` DESC
   LIMIT 1;
1 Like

As for “why never have an offer 0”…
1: Everyone will be flagged as already having seen offer 0. This is required to make the cookie make sense. (Otherwise the cookie would look like “,1,2” and that leading comma would be an issue)
2: Anything that PHP doesnt recognize as a number will be chewed up by intval and spit out as a 0.

1 Like

@m_hutley I am going to try to process this. This is all new to me and I do not just want to copy and paste. I would also like to understand it

To give you the most complete picture possible, this is the subscriber table

CREATE TABLE IF NOT EXISTS `newsletter_subscribers` (
  `subscriber_id` int(11) NOT NULL AUTO_INCREMENT,
  `subscriber_name` varchar(255) NOT NULL,
  `subscriber_email` varchar(128) NOT NULL,
  `subscription_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `subscription_token` varchar(255) NOT NULL,
  `subscriber_ip` varchar(32) NOT NULL,
  `isActive` tinyint(4) NOT NULL DEFAULT '0',
  PRIMARY KEY (`subscriber_id`),
  UNIQUE KEY `subscriberEmail` (`subscriber_email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

So, the long winded, old-school Variable-Tracing form of the logic is this:

1: Initial Trigger

Let us assume there are 4 offers active in our database. With ID’s 1,2,3 and 4.
The user has just signed up. We assign a cookie to this user, shown_offers, which contains the string “0”.

2: Initial Load

The user reloads the page (or we do it for him, whatever.)
Our cookie-sniffing PHP code says “Ah. This user has a cookie, we should look for an offer to serve them.”
PHP takes the string “0”, explodes it. This returns an array, [“0”]
That array has a map run over it, passing each value to the intval function. For sake of brevity, I believe we can all understand what that function does, and thus the map function returns [0].
Implode then smashes the array back into a string, “0”.
Yes, this is the same string as before. But now we know for certain, because intval can only return integers, that the string contains only numbers and commas. No malicious code, no strings, no weirdness. So it’s safe to hand to our database execution engine.
We tell the database "Find me an offer, that is active, but is not in the set “0”. Give me only 1 of them, and make it the highest offer ID. Database does its thing, and spits back an answer: 4.
We serve Offer 4 to the user.

3: User has closed an offer.

We served offer 4 to the user. He’s seen it, and closed it. We append “,4” to the cookie, making it now read “0,4”.

4: User has reloaded the page again.

Our cookie-sniffing PHP code says “Ah. This user has a cookie, we should look for an offer to serve them.”
PHP takes the string “0,4”, explodes it. This returns an array, [“0”,“4”]
That array has a map run over it, passing each value to the intval function. The map function returns [0,4].
Implode then smashes the array back into a string, “0,4”.
We tell the database "Find me an offer, that is active, but is not in the set “0,4”. Give me only 1 of them, and make it the highest offer ID. Database does its thing, and spits back an answer: 3.
We serve Offer 3 to the user.

Use case: We added an offer, 5.

Well we added an offer. It’ll have a higher offer_id. So the next time the user with the cookie comes back, the system will process the code, and hand the user that offer first. Offer 5 is shown to the user.

Use case: We deactivated an offer the user has not seen. (Offer 2)

Then the query won’t find that offer the next time the user comes to the site, because it no longer matches the isActive = 1 clause. The query will find the next active offer that hasn’t been shown to the user, and show them Offer 1.

Use case: We deactivated an offer the user has seen.

Then the query won’t find that offer the next time the user comes to the site, both because it no longer matches the isActive = 1 clause AND the offer id would be in the set of already-seen offers.

2 Likes

I think I understand what you mean, but where do I set the

( `$sanitized = implode(",",array_map(intval,explode(",",$cookiestring)` )

This is going way beyond my knowledge

Let me first explain how I have it now.

  1. Person visit website
  2. Popup modal (mailinglist) appears
  3. When they subscribe (double verification) Cookie newsletter_shown is set (on second verification)

After that the offers should appear, when available

$sanitized is a PHP variable. (I know $ is a legal starter for javascript variables, but PHP variables must start with $. So by default people will assume things that start with $ are PHP). You set it inside the PHP, before you execute the database query.

@m_hutley Can we please take this step by step, because I try to get my head arrount this without success sofar.

First step. Someone subsribes to the mailing list (The first Cookie is set:

Cookies.set('mailinglist_popup', 'yes', { expires: 1000 });

The person receives a thank you email with a link in order to confirm there subsription Clicking the link will bring them to a thank you page where a second Cookie is set:

Cookies.set('mailinglist_active', 'yes', { expires: 1000 });

And this is the point where I am loosing you. So any input from here would be more than welcome.

Thank you in advance

So, which part of the step by step post above are you getting stuck at?

@m_hutley O.k. let me try and start with steps 1 and 2. In the alternative approach, when someone has subscribed to the mailinglist you write to asign a cookie which contains “0” Would that be something like:

setcookie('shown_offer0', 'shown_offer0', time() + (86400 * 30), "/");

If this is the case. The following step in your approach would be if an offer was shown to append the offerid to the existing cookie

This is the first part where I am confused about. How do I append that id to the existing cookie?

Sorry for my ignorance but I really have no idea :frowning:

=>
setcookie('shown_offer', '0', time() + (86400 * 30), "/");

(Assuming name,value,expiry,domain as the parameters of that function, though I’m surprised the last one is just “/”. Maybe the function does some automatic figuring out of what root domain to use.)

1 Like

I found the example of setting a Cookie in a Tutorial. So I just took that example.

Ok so now the cookie is set. That brings me to the second and third question. In your alternative method, you define the variable $ Cookiestring in the implode function at a certain moment:

($ sanitized = implode (",", array_map (intval, explode (",", $ cookie string))));

So my next question is where is this Variable created and how do I ensure that I can then use it in my query.

The third question is, as already stated in item # 66, how do I then add the viable $ offerid to the already existing Cookie

Well you also displayed a knowledge of using Cookies.set in #64, so… I would stick with a single method of manipulating cookies :stuck_out_tongue: Cookies.set('shown_offer','0', {expires: 100000000000}) or some such.

That variable is just the value of the cookie. You’ve demonstrated a working knowledge of how to access the value of a cookie inside PHP in post #5.

Get the value of the existing cookie, append the new ID to it, and Set the value of the cookie in precisely the same way that you set it the first time, just with the new value.

Your right. I was mixing things up. I will stick to one method:

Cookies.set('shown_offer', '0', { expires: 1000 });

Sorry again for my ignorance. But in Post #5 I checked if a certain Cookie was set where in your example $cookiestring is holding multiple $offerid’s (Array of id’s) from the offers that where allready seen. or am I wrong?

But how do I get the value from from the existing Cookie, This is what is confusing me a lot. I really like to understand this, beacause I think it is a very good solution

No, $cookiestring in my example is the string inside the cookie… hence… the name. Also hence me saying in my step by step walkthrough (that you read, right?)

I mean… i provided a link to the PHP function and everything. I’ve walked the horse to the water at this point, and dunked its head in.

I feel like this means you’re just taking peoples code, not actually understanding it, and pasting it into your file. So… go read the basic usage guide for js-cookie, that thing you’re using to set the cookies, and then you tell me how you get the value of the existing cookie.

@m_hutley Sorry for not understanding you :banghead:

As you can read back in post #58.I don’t want to just copy and paste, I would like to understand it. I know you can get the value from the Cookie using:

Cookies.get('shown_offer');

But what I don’t understand how to append the new offerid to this Cookie And at what moment in my code I should do that

(Thank you @Technobear for splitting the post for me :slight_smile: @donboe , I felt that we had wandered too far away from the OP of that thread to make the conversation on-topic, so I asked for the thread to be split.)

The value returned from that function is a string. You want to append a string. How do you append a string to a string in Javascript?

Once you’ve appended the string… you want to set the cookie to have the appended string in it.

When you consider the offer to have been properly served. Do you consider that… when the offer is loaded? When the offer is actually displayed on the screen? When the offer is closed? That’s a design decision that only you can answer.

1 Like

Probably you think I’m stupid but to test I did the following:

<script>
var offerid	=	1;
Cookies.get('shown_offer') + offerid;
Cookies.set('shown_offer', 2, { expires: 1000 });
</script>

I simply don’t see it. In the Console I don’t see multiple values. Again sorry. I would understand If you’re getting tired of it all

You’re not catching the result of the second line. What you’ve said is:

var offer = 1;
"0"+1; //This line doesnt do anything... Also it's not quite what i told you to do, because you're missing the comma.
Cookies.set('shown_offer', 2, { expires: 1000 }); // where'd the 2 come from?