I am currently writing a Magento 2 module that requires me to log customer actions like product views. This action needs to be added for both logged in customers and guest customers. My solution is to use a custom variable (array) in the session for the customer of all product ID's.
To get around full page caching I have implemented a frontend ajax request to log the product views.
I have a controller that when visited will save the product ID in the session. This works as expected when I visit the URL directly, however, when its visited via an AJAX request the saving of the session variable does not work.
I have spent hours trying to debug this, I have been outputting the contents of the session variable and when accessed with AJAX I can see the contents, it's just never updated.
```
public function setGuestCustomerProductView($productId)
{
$guestProductViews = $this->_sessionManager->getGuestProductViews();
$guestProductViews[] = $productId;
$this->_sessionManager->setGuestProductViews($guestProductViews);
return $guestProductViews;
}
```
The AJAX request will always return the contents of the session variable (plus the product ID you are viewing) but never sets the variable. If I visit the URL directly in the same browser the contents are shown and the session variable is updated.
Further AJAX requests show the new session variable data from the direct URL request.
Have I misunderstood something in regards to sessions and AJAX requests? The domain is the same so there is no cross domain issues.
Any help would be appreciated.
UPDATE
I am starting to think this is not a magento 2 issue and it's more of a general Session/AJAX issue.
I decided to test a theory and switch out the SessionManager and use PHP's $_SESSION global variable. This resulted in the same issue so it's not the handler that's the issue.
Further tests concluded the same session ID was being passed and used correctly. While using the SessionManager I called isSessionExists() directly before the set method. This method returned true which checks for not only a valid session ID but also confirms the headers haven't been sent.
I see no reason why this works directly in the browser but not over AJAX. I will continue to investigate unless someone posts and answer I can try out.
SECOND UPDATE
After several failed attempts to get this feature to work I have decided to drop the feature and try a different implementation. As it stands in my module I am not using cookies on the clients side to record the product views and then reading the cookie in PHP. This works perfectly.
I hope my investigations here helps someone in the future.
Related
I'm on a Production System 6.4.2.1, but had the same problem on a newer version 6.4.14
If you enter the shop for the first time with a query parameter URL for example https://shop/?affiliateCode=test&campaignCode=test, the codes will not be saved to the session to use it for example in the cart or have this flags on an order (which is standard shopware function).
After you entered the shop you have to navigate to another page than paste in the url with query parameter to get it saved to the session.
If you than delete your site data and enter the shop again with this
query parameter url its not working again.
This issue happens only in production if cache is turned on.
As far as I could investigate this issue I noticed that for the very first time symfony fires the "BeforeSendResponseEvent" which Shopware listens to but this just terminates the first request with our query parameters
So now if you navigate to another page and enter the url with query parameter again, than Symfony will trigger the KernelEvent which Shopware listens to to add the query parameters to the session.
Did anyone else had trouble with this issue before?
Yeah, I think you got it right. Looking at the listener the corresponding event isn't dispatched if the http cache is hit. The affiliate and campaign parameters become part of the cache key and therefore consecutive requests will result in cache hits, avoiding the listener.
I think your best bet might be to create a ticket on the issue tracker. Ultimately this will need to be fixed in the codebase.
For now the only way to be sure the codes are stored in the sessions would be to publicize URLs with the parameters on routes that aren't http cached, like /account/register. For workarounds you could register your own controller that avoids the http cache and redirects to the home page, just for the sake of not missing these parameters. Another option would be to listen to to HttpCacheHitEvent as described here and set the codes to the session yourself, even though you might also have to start the session at that point.
Background:
I'm developing a website tracker using javascript. Here's how it works:
1) A user visits any domain the tracker script is on "anydomain.com". The script makes a successful ajax call in the background to my master domain "masterdomain.com".
2) When "masterdomain.com" receives a request, the following PSEUDO code is run. It works by checking for an existing session and if one doesnt exist it creates a new one.
The first call appears to be fine because I am able to receive a session ID in a response. However, each successive call to "masterdomain.com" creates a new session. AKA the server doesn't find the "should be" existing session.
Sample PSEUDO Code:
if(session exists)
{
// update timestamp for session
}
else
{
// set a new session for visitor
}
// load template
api(array("accepted"=>session_id),callback);
Some Quick Facts:
1) This does not appear to be a same origin issue (as I am able to communicate with the server fine).
2) I have tried this with cookies/sessions both appear to not be working.
3) I am using codeigniter (sessions are set not to expire on page close). I have also tried using/not using database sessions).
This problem can also be solved if there is another way to uniquely identify a user each time a page loads on a server (not using IP).
Any help would be greatly appreciated as I'm about ready to tear the rest of my hair out of my head!!!! :(
This answer is incomplete in that you'll have to do some additional research, but the easiest way (which is not actually particularly 'easy') to do this is to use Javascript to place a hidden iframe to masterdomain.com, and set up iframe communication (e.g. using postMessage) to retrieve the session from that iframe to your page.
With AJAX calls you can only send/set session cookies if the URL you're calling is on the same domain as your calling script. I think you should create an iframe, call ajax from within and it should work fine. By the way, I have no idea what you are trying to track.
Everything is working fine if all the processing happens on my own site. The session variable get stored and retrieved successfully.
Now I got a third part integration, which is processed via POST data. I have got session_start() called at the first line of each php file.
start_process.php - sets some session variables as follows and calls third party that redirects to response.php
$_SESSION["id"] = $id // Echoing these shows the correct values
$_SESSION["name"]= $name // Echoing these shows the correct values
response.php - This page receives the response from the third party and tries to get the data from session variables
$id = $_SESSION["id"] // This comes out to be blank
$name = $_SESSION["name"] // This comes out to be blank
On my processing page i.e. the response.php, I am trying to retreive back the session values, I don't get the session variables back.
Searching on SO, few post suggest that to check the value of
echo session_id();
which comes to be as different on the first page and the later page coming back to my site. Searching further shows that the value of the following needs to be blank
echo ini_get('session.cookie_domain');
This indeed is blank. Now I am stuck as I see this value as blank, and even though the session is not getting loaded properly.
Can you please suggest what to do next? Any debugging? Any hints to solve this problem?
Update
start_process.php
has a form whose post action is the url to third party site... as
<?php session_start();
$_SESSION["Check"] = "Abc";
echo session_id();
>
<form name="myform" action="http://<ThirdPartyUrl.com>/pathToSomePage.jsp" method="POST">
<!-- some hidden fields with value and some other text fields -->
</form>
respone.php
The third party gives a response in post request again to my response page where I directly test the output of the POST variables and here I am trying to use my session variables
<?php session_start();
echo $_SESSION["Check"];
echo session_id(); // This is different from the one printed in the start_process.php page
?>
I don't think the third party hosting is on the same server, because currently I am on a shared host and the third party definitely has it's own server.
It's hard to know without seeing some more code (how start_process.php is hooking into the third-party code, how the third-party is coming back to response.php). Here are a couple guesses:
Theory 1: third-party code is messing with your session (if hosted on the same server)
Is this third-party integration hosted on your same server? If so, I would suspect that the third-party could be ending/recreating, or otherwise modifying your session.
Theory 2: third-party is redirecting back to your site using a separate domain
Is it possible that you start off at mydomain.com and the third-party redirects back to www.mydomain.com (or something like that)? Even though those two domains look like they should be the same, they are utterly different as far as PHP sessions are concerned, you'll end up with a different session.
I've dealt with a similar problem when working on shopping cart payment gateway integrations. If the response script is ultimately contacted via the browser (i.e. the user is redirected to response.php after they're done on the 3rd party site), the session IDs and cookies will be preserved. If your response script is contacted via a server side request from the 3rd party site, that request is treated as an entirely new session. In that case a lot of integrations allow you to senda "passthrough" variable that will be sent back to your response script along with the rest of the data generated by the 3rd party site. You can use this variable to connect the user's session to the server side request you receive later on (for example you could create a database that relates the two values). Alternatively you could "cheat" the system. If you're passing the response script location along with your request every time, you could build your own passthrough variable into it. So instead of something like
<responseURL>www.mysite.com/response.php</responseURL>
you could send
<responseURL>www.mysite.com/response.php?key=abcd1234</responseURL>
I would recommend setting the key parameter to the session ID directly, so you'd have to build something simple that could translate between the two (like the table I mentioned above).
First of all you need to start a session before to use it. Before assign any value to a session valiable type into your code: session_start(); Do not forget to destroy/unset the session eighter. Hope it will work
Use cookies with some specified expire timings ! it will works well. updated your question with some code so coder can debug it !
Short answer is: find the cookie!
You can loose at domain or directory level. See session_set_cookie_params() specs.
What about the 3rd part. Does response.php requested from the same browser or from another web app, so have it the same cookie? It seems to me that doesn't.
To solve the problem is required to analyze the process steps to determine the place of every execution
If the thirdparty application is calling itselft to the URL of the response and is not a redirection into the client the sessions are not the same.
Example:
Client navigates to start_process.php and a session is created for client
start_process.php calls the thirdParty
Thirdparty app calls response.php and a session for thirdparty is created
Is important to check that the session ID is maintained by the client cookie and validated in the server. The client that starts the process and the thirdparty are diferent "clients" of the app with their own sessions.
Diagram example that shows you are probably doing based on your question.
Probably you can't call the third party directly from the client. On the client call a page on your host that calls the third party and capture the response (for example using curl)
Diagram example:
We have a legacy (php) aplication, accepting file uploads and they are stored at a path depending on the session id. Now we had to provide a very simple API for this webapp, where through an iOS api (iPad) a file upload is performed. We return an url which the customer will open in an embedded webkit window.
Because the sessions from the upload and view actions are different, we thought to grab the session parameter and return it in our response from the file upload. Then the client gets redirected to that url, we set the session id to the previous id and continue to the page the customer can continue the work.
Apparently, nothing I tried works. We use Zend Framework 1, but that shouldn't really matter. I tried:
Setting a Set-Cookie header (this results in a cookie containing two PHPSESSID values)
Use a setcookie("PHPSESSID", $session, 3600) to set the PHPSESSID
Use the Zend http Reponse with a setHeader('Set-Cookie', 'PHPSESSID=....', true)
The last two options just don't do anything, like I didn't set the session at all. How can I solve this? We actually can't touch the legacy code base that much to modify its working and change the way the path resolving works for file uploads.
So, the flow is:
Request to api.myapp.tld -> Response with a string in body -> Open webkit window with this response string as location -> Request is performed -> Response with a Redirect header and a method to set the cookie to something different -> Webkit performs redirect -> Customer gets to a page with same session ID as the first request to api.myapp.tld.
If there is an alternative to set the session id, it would be great.
That's not trivial to debug, but you have some options. I'm not fluent with Zend Framework 1.x, so this is not framework specific (frameworks sometimes add stuff on top), but PHP specific.
In PHP a session is identified by two things:
Name (example: a common default name is PHPSESSID)
ID (that is the random "number")
The Name allows to use multiple sessions at once, while the ID identifies the session in specific.
It sounds a bit you need to use two session IDs in parallel. I suggest you make the script that needs to deal with the legacy session to have another sessions name than your current script.
You can then pass in the legacy/old session id by using the other session name while your current session can remain as is.
I hope this information is helpful. If you have got problems to implement that, please ask.
I ended up by something simpler. The session was related to the path like this /path/to/location/ . $sessionId. When the second session was started, I simply renamed the directory from the old session to the new one. Simple and fast to get this working.
How reliable is a method of setting variables into a session and then retrieving them on another page?
I have a script where users drag and drop elements on a page utilizing jQuery UI. I record transactions using AJAX, however, sometimes I get results missing project ID, or to be exact I get 0. I set this ID into a session variable when users first get on this script page. The page has an included JS file with my functions and from there the transaction data is sent to an AJAX page where I store transactions into my db. Because the project ID is the same I get it from my session. It is not a consistent error, happens only once in a while, but it bothers me a lot.
Why is it happening randomly? And how can I fool-proof my code?
UPDATE: OK, it seems it's something else that may be interfearing with that particular session ID.
I do have session_start(); on every page where I use sessions and I set them the same way I set all my sessions: `$_SESSION['project'] = $projectID;
Back to debugging...
Yes, you can rely on PHP sessions. If you are getting odd results, it seems like your going to have to debug your code until you find the issue.