How to correctly read Javascript hash in custom affiliate URL? - javascript

I'm creating a custom affiliate program. I want my links to be as SEO friendly as possible, so I will use a Javascript hash appended to the URL to send the affiliate id, read the affiliate id, store the click, and then 301 re-direct to the page they were linked too. That way we have no canonical issues whatsoever, and every affiliate link passes link juice!
Now, how would I read the following URL?
www.mydomain.com/seo-friendly-url#ref=john
After getting the hash value for ref and adding the click, how would I then 301 re-direct the user back to
www.mydomain.com/seo-friendly-url
Any help is greatly appreciated!

Fragment identifiers (the part after the #) are not sent to the server, so they cannot be read by anything that could then emit an HTTP response (which you need for a 301 redirect).

The "hash" portion of a URL is not passed to the server, so you will not be able to utilize this data for any server-side redirection or processing directly. However, it is possible to grab the hash on page load and pass it on to the server via AJAX or redirection:
To immediately redirect a user from www.mydomain.com/seo-friendly-url#ref=john to www.mydomain.com/seo-friendly-url/ref/john
if (window.location.hash.match(/#ref=/))
window.location = window.location.href.replace('#ref=', '/ref/')
... but then, why not have just used www.mydomain.com/seo-friendly-url/ref/john to begin with and save the extra leg work? The other route, through AJAX, involves reading the value of the hash after the page has loaded and sending that off to the server to be recorded.
(note: this code uses a generic cross-browser XMLHTTPRequest to send an AJAX GET request. replace with your library's implementation [if you are using a library])
window.onload = function () {
// grab the hash (if any)
var affiliate_id = window.location.hash;
// make sure there is a hash, and that it starts with "#ref="
if (affiliate_id.length > 0 && affiliate_id.match(/#ref=/)) {
// clear the hash (it is not relevant to the user)
window.location.hash = '';
// initialize an XMLRequest, send the data to affiliate.php
var oXMLHttpRequest = new XMLHttpRequest;
oXMLHttpRequest.open("GET", "record_affiliate.php?affiliate="+affiliate_id, true);
oXMLHttpRequest.onreadystatechange = function() {
if (this.readyState == XMLHttpRequest.DONE) {
// do anything else that needs to be done after recording affiliate
}
}
oXMLHttpRequest.send(null);
}
}

Related

Redirect to URL from URL

I am wondering how to deal with a simple redirect. I have a domain, for example: stackguy.com. And I want to redirect users to specific URLs from this url.
Let's say, stackguy.com/redirect=youtube.com/watch/xxx
And this URL (youtube.com...) needs to be elastic. What the user enters, it should redirect to the website the user wants.
I have totally no idea, to be honest. I've tried to do it by using database and by separating all urls but it's a lot of work and can't be automated easily.
It can also be done like stackguy.com/red=<id of YT video>
Doesn't matter to me.
The other solution talks about using javascript which runs on the client side. And you probably want this on the server side.
You still need to use a parameter
stackguy.com?redirect=https://www.youtube.com/watch/xxx
But you can use php to do the redirect.
$par = filter_var ($_GET ['redirect'] ?? '', FILTER_SANITIZE_STRING);
if ($par)
{header('Location: ' . $par, true, 302); }
The first line gets the parameter after sanitizing it. It returns blank if its null (or missing)
The second line checks if there is a string
The third line does a redirect using a 302. This is a temporary redirect, I wouldn't advise using a 301 (permanent).
Note that this will only work if the PHP file has done NO HTML output.
I think you should use query parameters for this and handle the redirect in your javascript. Instead of:
stackguy.com/redirect=youtube.com/watch/xxx
use
stackguy.com?redirect=https://www.youtube.com/watch/xxx
Then in your js you can check if the redirect paramter is set and redirect the user to the link in the query parameter.
Here is an example:
function redirectUrl() {
// Get the value of the "redirect" query parameter
const redirect = new URLSearchParams(window.location.search).get("redirect");
// If the "redirect" parameter is not null, redirect the user to the specified URL
if (redirect) {
window.location = redirect;
}
}
To use the function you will need to call it in your code for example:
window.addEventListener("load", redirectUrl);

Use URL to jump to a page in AJAX

My website structure is as follows:
public_html/
- index.php
- students.php
The user loads the site (index.php) which contains a button. When this button is clicked AJAX is used to load "students.php" and it is displayed to the user (As if they just went to a different page seamlessly). When doing so the following JavaScript is run:
var state = {'Page' : 'Students'};
history.pushState(state, null, "students");
This adds a state to the browsers history and causes the browsers URL to display "example.com/students" instead of "example.com". However if a user was to refresh at this point, nothing would load (404 Not Found) due to the folder "students" not actually existing.
My question is, how can I get the users browser to actually display "index.php" and automatically take them to the students page. In other words, the user refreshes "example.com/students" and what actually happens is the user is taken to the index.php file and the AJAX automatically takes them to the students page (As though they actually refreshed the page)
Note: I am aware I can pass null to the url parameter in "pushState()" however this URL behaviour is desired as it would allow users to quickly jump to a page (If I can get it working)
The full code to show the students page via AJAX is as follows:
/**
* Display students screen.
*/
function displayStudents(createState) {
if(typeof(createState)==='undefined') {
createState = true;
}
$("#container").css("width", $( window ).width());
$("#container").css("position", "fixed");
$("#container").animate({marginLeft: "-100%"}, ANIMATION_SPEED);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
$("#container").css("margin-left", "100%");
$("#container").html(xmlhttp.responseText);
$("#container").animate({marginLeft: "0"}, ANIMATION_SPEED, null, function reset() {
$("#container").css("width", "100%");
$("#container").css("position", "relative");
});
if(createState) {
var state = {'Page' : 'Students'};
history.pushState(state, null, "students");
}
}
};
xmlhttp.open("GET", "students.php", true);
setTimeout(function() { xmlhttp.send(); }, ANIMATION_SPEED);
}
Most of the code here is for animation.
In other words, the user refreshes "example.com/students" and what actually happens is the user is taken to the index.php file and the AJAX automatically takes them to the students page (As though they actually refreshed the page)
The point of pushState is that when you use JavaScript to transform the state of the page, you provide a URL which the server can use to deliver some HTML that will provide the page in that state.
If you are always going to serve up the homepage and then transform it with JavaScript, then just use hashbangs. pushState is entirely the wrong tool for the job.
If you were to use pushState, then a pseudocode implementation of a possible approach would be along the lines of:
GET data needed for the page
IF `Accept` header prefers `application/json`
Output `Content-Type: application/json` header
Output data in JSON format
ELSE
Output `Content-Type: text/html` header
Pass data through the template for the page
Output template as HTML
And you would use students.php in the URL instead of students (or you would make students resolve to the PHP code you wanted to run instead).
Since you are using raw XMLHttpRequest, you will need to use setRequestHeader to set the Accept header. You are using jQuery though, so you could just use $.ajax and pass it dataType: "json".

Can i pass information through the URL when i am using jQuery Mobile?

I have a mobile application that opens an in-app browser that uses the URL to pass information to my server , like the deviceID.
For example the browser will open the web-page (jquery Mobile) : www.myserver.com/doWork.html#deviceID
On the server part using JavaScript inside the doWork.html file, I get the deviceID like this:
var userId = window.location.hash.substring(1);
Is it ok that i pass information using the hash # ? In jquery mobile the hash # is used to change between pages when someone uses the Multi-Page template structure . So i am afraid that maybe i should use something else , like a question mark (?) ?
Or its perfectly fine ?
NO. Stop using # for your data transfers. Let jQM do its thing. Don't disturb it. Use Query strings( adding ? in url). My advice is to stop using query strings (? tags) and # tags to send data to the next page. Handle it using localStorage. Its more secure compared to Query strings because the user wont see the URL change, so your sensitive data is hidden, at least to a little extent. localStorage is HTML5's API which is like a temporary storage set aside per domain. This data will persist until data is cleared in cache. Assuming you have an anchor tag which goes to dowork.html,
Go to Do work
Add an attribute for device ID in the tag itself, like this :
Go to Do work
You'd be doing this dynamically you might also use it the same way. You get the gist right?
A click event for this would look like this :
$(document).on("click", "a", function(e) //use a class or ID for this instead of just "a"
//prevent default
e.preventDefault();
//get device id from tag attribute
var deviceId = $(this).data("deviceid");
//set it in localStorage
localStorage["dId"] = deviceId;
//redirect
$.mobile.changePage(this.href);
});
Then, in the other page's pageinit (or any event), get the device id from storage and send the ajax call to the server.
//assuming #dowork is the id of a div with data-role="page"
$(document).on("pageinit", "#dowork", function() {
//get from storage
var deviceId = localStorage["dId"];
//make ajax call or server call with deviceId here
});
But, if you still want to use URL for this, look at this question. I've given a decent enough answer over there.
To pass variables to the server you should avoid using the # symbol because regardless of the framework you are using this symbol is used for other purposes, to pass info to the server in a GET request you should use the ? symbol, something like this should do it: www.myserver.com/doWork.html?deviceID=1233455

Window Event when "?" added after current URL

Hashchange is for when
index.php
Changes to, say
index.php#my-hash
i.e.
$(window).bind('hashchange', function() {
// do stuff
});
But is there an event for when there is a ? after the url, i.e.
index.php?id=foo&something_else=bar...
Edit
Okay, it's when I submit a form. I submit the form and then the URL changes to
index.php?id=blah#my-hash
However I tried listening for a) the hashchange and b) the form submit:
$('form').submit(function() {
go_to_signup_form();
});
Neither of which work (I think the page is refreshing?). I can't alter the php too much because it's part of a cms and I don't want to break anything that's happening in say, the controller class so I would rather just try to see when:
index.php
changes to
index.php?id=blah#my-hash
Edit #2
Thanks everyone for the feedback, got it working with:
if (url.indexOf("?") !== -1) {
go_to_signup_form();
}
Nope, that is because the parameters (?foobar) aren't usually used for client-side code. Linking to a new parameter on the same url (index.php -> index.php?foo=bar) makes your browser load a new page, while adding a hash (index.php -> index.php#foo=bar) does not make the browser transmit any data to the server.
The hash section of a url, it's a client-side piece of data. As such, it is useful to have a change event listener for it.
Try these in your console, on a random site that doesn't have a hash in the url yet:
window.location.href += "?test"
and:
window.location.href += "#test"
You will see that the first one will reload the page (Send a new HTTP request), the second one will not appear to do anything.
To prevent a form from submitting:
$('#target').submit(function() {
// Your onclick code here
return false; // Do not submit.
});
The problem with that is that the "hashchange" (technically it means navigation to an anchor) is an entirely client-sided operation. But an URL with arguments (the "?" operator) is fulfilled with a new HTTP request to the server, which results in a new document being sent to the user. That means when a user clicks on a link index.php?id=foo, the page is reloaded.
But you can check the arguments of the URL the page was loaded with by examining the window.location.href string.

Make an ajax request to get some data, then redirect to a new page, passing the returned data

I want to redirect after a successful ajax request (which I know how to do) but I want to pass along the returned data which will be used to load an iframe on the page I just redirected to.
What's the best way to pass such data along and use it to open and populate an iframe in the page I just redirected to?
EDIT:
I am passing a GET variable but am having to use the following to access it for use in my iframe src attribute:
function $_GET(q,s) {
s = (s) ? s : window.location.search;
var re = new RegExp('&'+q+'=([^&]*)','i');
return (s=s.replace(/^\?/,'&').match(re)) ? s=s[1] : s='';
}
var d = $_GET('thedata');
I assume there isn't really a more straightforward way to access the GET vars?
If it's not too much data, you could pass it as a get parameter in the redirect:
document.location = "/otherpage?somevar=" + urlescape(var)
Remember that urls are limited to 1024 chars, and that special chars must be escaped.
If it is beyond that limit your best move is to use server side sessions. You will use a database on the server to store the necessary information and pass a unique identifier in the url, or as a cookie on the users computer. When the new page loads, it can then pull the information out of the database using the identifier. Sessions are supported in virtually every web framework out of the box.
Another alternative may be to place the data as a hidden attribute in a form which uses the post method (to get around the 1024 char limit), and simulating a submission of the form in javascript to accomplish the redirect, including the data.

Categories