PHP: Changing referer with header() - php

My CMS links to other sites for convenience and I'd like to hide the referer so that other sites don't see the directory and the query string of my CMS. I now have the CMS linking to a PHP file elswhere on my server which in turn redirects to the link via header() but the referer is still from my CMS, not from the linking PHP. Furthermore...
header("Referer: nowhere");
header("Location: $_REQUEST[urltolinkto]");
... doesn't appear to change anything. No matter what I put as referer, it's always the one from my CMS where the user actually clicked on the link.
Can the referer be changed (to the linking PHP), or do I have to use javascript or meta refresh?

The Referer header is something the browser sends to the Server. You are changing the respose from the server to the browser, so that will not work this way (unlike the Cookie header). As far as I know you have no server-side control of the browser's behavior on sending the Referer.

The browser does get to choose what referrer to send, but there are ways around it.
HTML5 added meta referrer, most modern browsers will respect it. Just add
<meta name="referrer" content="no-referrer">
to your site's head.
There's also redirection services and other hacks to hide the ref (https redirects, iframe tricks and others).

A good solution is to simply use the classic <META HTTP-EQUIV="REFRESH" CONTENT="0; URL=http://www.example.com/">.
In fact, Google Analytics has a help page specifically for this question with users who ask about web-tracking not working on redirects, here: Support.Google.com -> Redirects: Place the tag on redirecting pages. They explain the problem quite well:
If your site uses redirects, the redirecting page becomes the landing page's referrer. For example, if you've changed your site so that index.html now redirects to home.html, then index.html becomes the referrer for home.html....
For this reason, you should place the Analytics tag on the redirecting page as well as on the landing page. This way, the redirecting page will capture the actual referrer information for your reports.
So, just swap out header("Location...") with a massive series of print statements. This feels so inelegant. But it works.
Note: I'm also throwing in a canonical attribute so browsers understand the point of the redirect more clearly.
<?php
$redirect_url = 'https://www.example.com';
$google_analytics_configgtag = '12345, this is your api key';
print('<!DOCTYPE HTML><HTML><HEAD>');
print('<META HTTP-EQUIV="REFRESH" CONTENT="0; URL=' . $redirect_url . '"/>');
print('<LINK REL="CANONICAL" HREF="' . $redirect_url . '"/>');
if($google_analytics_configgtag) {
?>
<!-- Global Site Tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=<?php print($google_analytics->configgtag); ?>"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', '<?php print($google_analytics_configgtag); ?>');
</script>
<?php
}
print('</HEAD>');
print('<BODY></BODY></HTML>');
?>

You cannot set Referer header manually but you can use location.href to set the referer header to the link used in href but it will cause reloading of the page.

You cannot really change the referer from server-side as it is provided by the browser to the server.
But you can use a service like href.li, just use
https://href.li/?http://<your-url>
Note: http:// after ? is important or it will not redirect.

Related

PHP - Delay on redirect

I'm using the following code to use as a form of nulling referring script and it works perfectly but it just redirects them straight to the target URL.
How would I go about creating a 5 second delay so I can display some adverts for 5 seconds before redirecting them?
You can send php header with timeout refresh. http://php.net/manual/en/function.header.php
<?php
header( "refresh:5; url=wherever.php" );
?>
What about using sleep()?
function method1(...) {
sleep(5);
... rest of the code
Note however that it is more recommended to use Vahe Shadunts's answer, which uses header() instead.
The refresh header does the job but I'd like to highlight some potential issues:
It is not specified in the HTTP standard. Wikipedia says:
Proprietary and non-standard: a header extension introduced by Netscape and supported by most web browsers.
But it has been around for almost 20 years now and I don't know of any browser that does not support it (could not find a reference though)
Some browsers do not use the cache on a page redirected with refresh. It has been demonstrated for Internet Explorer here: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/meta-refresh-causes-additional-http-requests.aspx and I coud reproduce it on Firefox. Chrome does not have this issue.
Alternative: JavaScript
You can add a JavaScript on the intermediate page, that opens a new page after X seconds. Add this at the bottom of the page to redirect to http://www.example.com/target after 5 seconds:
<script type="text/javascript">
window.setTimeout(function() {
window.location.href='http://www.example.com/target';
}, 5000);
</script>
Combination
As a bonus, you can fall back to the refresh header if JS is disabled, using the meta directive http-equiv that tells the browser to act as if a certain HTTP header has been sent. Because it is part of the HTML source, you can wrap it in a <noscript> element. Add this to your <head> additionally to the JavaScript above:
<noscript>
<meta http-equiv="refresh" content="5;url=http://www.example.com/target" />
</noscript>
Now, the page redirects with JavaScript if available for the best performance, and uses refresh otherwise.

HTTP Referrer on Redirection

I have a small script that redirects users to main site if they come from a banner on my/other remote sites.
<?
.
..
...
....
header("location:$golink");
?>
But google analytics will not show the referrer site (where the script is working) instead it shows the url where the banner is clicked. Obviously I can not keep a track of all sites where banner appears and dont want to. I want the refferer to be the site where the script is working. How do I have to use the $_SERVER['HTTP_REFERER']; in order to do this ?
GA has a method that will let you to override the default referring URL (document.referrer) with a specified value.
So if you want to keep the redirect server-side, you can append the referring URL as a query string param in your header() call, and then look for it on the target page and specify it as the referring URL.
I don't know how you are building your $golink variable, but basically you would add something along the lines of:
$golink .= "?ref=" . $_SERVER['HTTP_REFERER'];
Use a & instead of ? if there are already URL params, and the code above assumes using ref as the URL param, so use whatever var you want.
Then on your target pages, before your _trackPageview call, you would add
_gaq.push(['_setReferrerOverride', ref]);
ref would be a javascript variable with the value of the ref=xxx query string param. For some weird reason Javascript does not have a native way to grab URL param values, nor does GA provide an (exposed) solution. If you already have a solution on your pages for grabbing URL params (like something from a framework or a function you've already made) then use that. Otherwise it's pretty easy to find a javascript function that will do it for you.
There are a couple benefits to doing it this way:
You don't have to worry about the visitor seeing an interstitial page.
You don't have to worry about GA not getting a chance to fully load before redirect
You can see the referrers tied directly to your landing pages, because with the interstitial page, you will always see that interstitial page as the referrer, and will have to look at referring url reports for the interstitial page.
Yes, G.A is blind to this kind of server-side stuff. And their PHP Api is not helpful either.
However, you could have a short redirection page, holding the GA tag inside like this :
<html>
<head>
<title>A web page that points a browser to a different page after 2 seconds</title>
<meta http-equiv="refresh" content="2; URL=<?php echo $golink; ?>">
<meta name="keywords" content="automatic redirection">
<script>var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'))</script>
</head>
<body>
If your browser doesn't automatically go there within a few seconds,
you may want to go to
the destination
manually.
</body>
</html>
Notice the $golink variable in the meta tag.
If you use this, do not forget to replace UA-XXXXX-X by your real account number.
Credits : optimized GA tag goes to Mathias Bynens
[EDIT : javascript only version]
<html>
<head>
<title>Redirecting you...</title>
<script>var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'))</script>
<script>
<!--
if (window.addEventListener)
window.addEventListener('load', function() { window.location="<?php echo $golink; ?>"; }, false);
else
window.attachEvent('onload', function() { window.location="<?php echo $golink; ?>"; });
// -->
</script>
</head>
<body>
</body>
</html>

Stop other websites iframing?

We run an online service (aka a script) and we have discovered a few websites over the past few weeks putting our script on their site via iframe.
What precautions can we take to stop other people putting our site into theirs via iframe?
Thank you.
A more global solution would be something like this:
<script type="text/javascript">
if (top.location != location) {
top.location.href = document.location.href ;
}
</script>
Place it on the top of your page (inside the "head" tag).
On modern browsers, send the header X-Frame-Options with the value DENY. If it's a recent enough browser, it'll obey the header and tell the iframe to pack sand.

setting a url as visited

I have a
my_text
link on my page, and the following line in my_redirect_page.php:
header("Location: ".$mylink);
but after the redirection, if I click on back in my browser, the "my_text" for the link does not appear as visited (in purple, instead of blue). How do I work around this? Is there a way to change the visited property in php or javascript?
Thanks,
Dave
Not a terrific solution, but, in my_redirect_page.php:
<html>
<head>
<title>Redirecting...</title>
<meta http-equiv="refresh" content="0; url=<?php echo $_GET['link']; ?>">
</head>
<body>
Redirecting to <?php echo html_entities( $_GET['link'] ); ?>.<br>
If you are not redirected, click here.
</body>
</html>
Or something like that - the Page should load (thereby entering into the browser history) and then, with a delay of 0, load the targeted URL. Should, for some reason, the redirect fail, the user will see a page containing a link to the targeted URL.
I'm not sure this is possible, unless you change the way your redirects are done.
[This question][1] is basically a duplicate of yours, and the consensus was that none of the browsers allow you to set pseudo-classes (like :visited).
The easiest way to simulate it for the user is to set a CSS class which colours the link to look the same as a browser default or CSS-style visited link, which you can easily do in your view layer or by adding the class using javascript if the link appears in window.history.
You may also be able to push elements onto the window.history array, and have them appear in the browser history (and hence be given the :visited pseudoclass), but I'm not sure if that would work. Worth a try though.

How to prevent my site page to be loaded via 3rd party site frame of iFrame

How can I find out that my page is embedded as a frame to other site during page loading? I guess referrer request header can't help me here? Thanks.
You cannot check it from the server's side, but you can use javascript to detect it after the page has loaded. Compare top and self, if they're not identical, you are in a frame.
Additionally, some modern browsers respect the X-FRAME-OPTIONS header, that can have two values:
DENY – prevents the page from being rendered if it is contained in a frame
SAMEORIGIN – same as above, unless the page belongs to the same domain as the top-level frameset holder.
Users include Google's Picasa, that cannot be embedded in a frame.
Browsers that support the header, with the minimum version:
IE8 and IE9
Opera 10.50
Safari 4
Chrome 4.1.249.1042
Firefox 3.6.9 (older versions with NoScript)
Stackoverflow includes some JS to test it (master.js). This is the relevant part of it:
if(top!=self){
top.location.replace(document.location);
alert("For security reasons, framing is not allowed; click OK to remove the frames.")
}
But keep in mind that JS can be disabled.
For modern browsers, you can use CSP (Content Security Policy), which is a standard. The following header will prevent the document from loading in a frame anywhere:
Content-Security-Policy: frame-ancestors 'none'
(IE 11 needs the X- prefix, though). You can also change 'none' to the origin on which framing is allowed, such as your own site.
To cover the older browsers, this is best used together with #Maerlyn's answer.
you can prevent loading you page in an iframe with javascript
<script type="text/javascript">
if ( window.self !== window.top ) {
window.top.location.href=window.location.href;
}
</script>
this code change address of container of your page's iframe to your page address and force container to show your page.
Or you can block a specific domain if you don't mind your content in some locations but don't want it on a certain site. For example, if offendingdomain.com was embedding your content, you could do this:
<script type="text/javascript">
if(document.referrer.indexOf("offendingdomain.com") != -1) {
window.location = "http://www.youtube.com/watch_popup?v=oHg5SJYRHA0";
}
</script>
This would check the parent document's location and see if it's the offendingdomain.com that is embedding your content. This script will then send that iframe to a certain famous youtube video as punishment. In effect they just Rick-Rolled themselves.
Use javascript to check if it was loaded on iframe by placing the following script at the end of your php file and redirect to a page that displays warning or notice that your page should not be loaded using iframe.
<script type="text/javascript">
if(top.location != window.location) {
window.location = '/error_iframe.php';
}
</script>
<?php
header("Content-Security-Policy: frame-ancestors 'none'");
?>
Replace hosname to domain name
if (window.top.location.host != "hostname") {
document.body.innerHTML = "Access Denied";
}
I using this PHP code on top of the header
if($_SERVER['SERVER_NAME'] != 'yourwebsite.com'){
header('location: yourwebsite.com');
}
if someone did iframe your site it will redirect to your website

Categories