12

How to not copy my source code to other servers and provide them with a JS or iframe like the analytics and statcounter provide us?

I wrote a PHP script with JS that in it's basic description goes like this: When someone visits my website, gets a cookie with a value of a unique identification and at the same time using AJAX I make some checks and I save that same value to mysql accordingly. After this, if he visits again my site, (in most of the cases) a cookie is not created again.

In depth:

The cookie value is created with JS and I want to keep it that way for future enhancements.

My code (index.php, add-to-mysql.php) has JS and PHP.

I want to use this script in my additional domains, and some of them are in different server. But I don't want to put all my source files to there accounts.

The ideal for me is to provide them with a JS code, like the google analytics or statcounter give us (or alternative similar ways), an iframe... solutions like these.

When a visitor gets into their page, my mySQL in a remote server (my server) will be updated and a cookie will created on their site. Transferring data from and to.

Is this something possible to be made? If yes, how can I start studying for this? Can you provide me with some guidelines?

Thank you.

this is a block of code, the ajax function that posts the random number to the add-to-mysql.php file where i make some actions

$.ajax({
    type: 'POST',
    url: 'add-to-mysql.php',
    data: { one: hash }, //an antikatastiso to hash me to a ke kano to md5 meso php sto ajax vgenei to idio
    success: function(data) {       
        alert("success! X: " + data);
    }
});
EnexoOnoma
  • 8,454
  • 18
  • 94
  • 179
  • AJAX Requests are only possible if port, protocol and domain of sender and receiver are equal. You can work around this with CORS [https://en.wikipedia.org/wiki/Cross-origin_resource_sharing ], JSONP [https://en.wikipedia.org/wiki/JSONP ] or an iFrame. – Reeno Aug 08 '14 at 09:49

3 Answers3

9

It seems to me you have three options here.

1. Use JSONP

JSONP allows you to do cross domain ajax calls so that you can just call in to your home server from your other domains without being obstructed. This is probably the easiest route to go I'm thinking.

See here for a quick write up on how JSONP works:
https://stackoverflow.com/a/2067584/867294

jQuery supports jsonp so it's not to difficult to get started with:
http://learn.jquery.com/ajax/working-with-jsonp/

JSONP works by dynamically adding a script to the document that then calls a callback. The contents of ths javascript file need to be generated by the server, your PHP file add-to-mysql.php will have to echo out something like this:

<?= htmlspecialchars($_GET["callback"]) =>('someData you want to return');

You can access the one: parameter that was passed in from jQuery trough the $_GET array as well, as this is just a GET request.

From the client side you can call this route like so: Note that this will always be a GET request, all parameters will go trough the URL. The 'callback' parameter is the connecting factor here, it makes sure the PHP side knows what JavaScript function to generate.

$.ajax({
    jsonp: 'callback',
    dataType: "jsonp",
    url: 'http://my-server.com/add-to-mysql.php',
    data: { one: hash }, //an antikatastiso to hash me to a ke kano to md5 meso php sto ajax vgenei to idio
    success: function(data) {       
        alert("success! X: " + data);
    }
});

2. Use CORS

CORS will allow you to make ajax calls to a different domain then the one where your JS is running. This does however require you to send special http headers from the serving html page, so this does require you to modify the servers.

See here for a qucik intro on CORS:

http://www.html5rocks.com/en/tutorials/cors/

In short, the headers you will need to set from the serving html page are:

Access-Control-Allow-Origin: http://domain.com
Access-Control-Expose-Headers: list,of,headers

3. Posting to an iFrame

Posting trough a hidden iFrame is also an option. For this you need to set the target of a form to the name of the iframe, the advantages here is that you can use POST as well. You can submit and populate the form trough jQuery as well.

$('#one_input').val('someHash');
$('#myForm').submit();

You can just put everything in a hidden div if you don't want to show it on the page:

<div style='display:none;'>
    <form id="myForm" action="http://my-server.com/add-to-mysql.php" method="post" target="my_iframe">
       <input type="input" id="one_input" value="" />
    </form>
    <iframe name="my_iframe" ></iframe>
</div>

You could also just set the url of the iframe with your parameter if you don't need any feedback.

var hash = 'stuff';
document.getElementId('one_input').src="http://my-server.com/add-to-mysql.php?one=" + hash;

Extra

you could also use the iframe with Window.postMessage
Building on the previous example:

$('#my_iframe')[0].contentWindow.postMessage('hash', 'my-server.com');

But this requires you to have already a page loaded in your iframe that will then receive the message trough JavaScript, so I don't think this is what you are looking for.

Community
  • 1
  • 1
Willem D'Haeseleer
  • 19,661
  • 9
  • 66
  • 99
  • What about IE < 8? As it seems, jsonp is not compatible with IE < 8 http://stackoverflow.com/a/614006/1437261 – Gogol Aug 08 '14 at 09:52
  • 1
    If the OP needs IE < 8 support then I think it's best he states that explicitly in his question – Willem D'Haeseleer Aug 08 '14 at 09:55
  • @WillemD'haeseleer Thank you for this answer. Please tell me in a practical way (please, if your reply is long, update your answer), what changes have to be made to my files (index, add-to-mysql) and what do i provide them to run this? – EnexoOnoma Aug 08 '14 at 10:00
  • @Fataoulas I added some extra info for the JSONP method – Willem D'Haeseleer Aug 08 '14 at 11:23
  • 1
    It's worth mentioning that the OP can also use `window.postMessage` and an iframe although I admit it's a worse alternative. – Benjamin Gruenbaum Aug 08 '14 at 11:42
  • @WillemD'haeseleer thank you for the updates. I think I need one last modification. How can I use the iframe method but without the use of form? On load, the iframe does what i has to do. – EnexoOnoma Aug 08 '14 at 11:57
  • @Fataoulas added an example to my answer on how to do that – Willem D'Haeseleer Aug 08 '14 at 11:58
  • You don't need a hidden form if you use an iframe. You can still use ajax. That's a cleaner approach because you solution can be pure javascript and you can more easily separate the data from the logic that sends the data to your server. – rulio Aug 11 '14 at 16:10
  • @rulio, not sure what you mean, how are you going to combine an iframe with ajax ? – Willem D'Haeseleer Aug 11 '14 at 16:14
  • @willem-dhaeseleer I think I misunderstood your suggestion. I thought you meant include the main JS analytics code in the iframe then communicate with the iframe with postMessage. But it seems like you're saying to send form posts from the host page to the iframe. I think you'll run into some issues there. Like relying on jQuery being installed on the third party site. One of the big benefits of the iframe approach is that it mitigates the risk of conflicts between embedded code and native code. This is what I thought you meant: moving most of the JS to the iframe. – rulio Aug 11 '14 at 16:31
  • You don't need jQuery to submit the form, that was just an example. – Willem D'Haeseleer Aug 11 '14 at 16:37
  • @Fataoulas, did you manage to fix your problem ? Do you need any more help ? – Willem D'Haeseleer Aug 12 '14 at 12:03
1

Google Analytics provide an script that doesn't post data, it loads an script asynchronously (this is very important to avoid messing with load times of the original website), then it sends all of their info requesting for a .gif image. Your code should do a request to an url ending in .gif, with all the data in GET form. Do your magic and return a gif with size 1px*1px and no content.

Just request something like this

yourdomain.com/a.gif?cookie=1234aqfajsdlq....&uid=qekjlajdfa

Put all your data in there I recommend obfuscating it a bit, but that should help you avoid cors, iframes or jsop

EDIT

<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'id', 'domain');
  ga('send', 'pageview');
</script>

This was taken from GA. See that it creates a tag, with the async attribute to avoid load time issues (remember sync scripts stop the page rendering). Then it creates and array where it pushes all the info it needs in tuples. It defines ga in the window as a function that pushes all its arguments to a q. The you can create an script that takes all of the data you need, with js, cookies, domain, etc. and send to the server. For example, you want the domain that the user is visiting:

//You won't have jquery, but you get the idea
//Create a tag
var i = $('<img>').prop('src', 'yourdomain.com/a.gif?domain' + window.location.origin).css('display', 'none');
$('body').append(i);

In some point you will have to set a cookie. I thing cookies can't not be cross domain, so you should set them in your requests not in js. On the server side you check the cookie, if there is none, you created, and there you can track many things.

Afterwards, your script can check for cors support, and use ajax without this. I don't recommend JSONP, is very error prone, and is actually kind of a hack

Nickydonna
  • 802
  • 1
  • 5
  • 18
0

In order to avoid the cross-domain problematic you can include an iframe at the other sites, that loads from your site. It creates its own scope (domain) and you can freely use ajax from inside communicating with your site. However, if you set cookies there, it will be associated to the iframes source domain (your domain). This might or might not be a problem. Note, that this can be used to identify users across all the other domains including this same iframe (from your domain).

fast
  • 885
  • 7
  • 15