Track What Visitors Copy From Your Site in Google Analytics
As you might be able to tell, it’s important for me to know if people are copying scripts from my site. To me, if a high proportion of visitors are copying my code, I know I’ve done my job. It’s simply a fancy way for me to determine engagement… but it’s not a typical behaviour to track – especially not in GA.
A few years ago, you may have read my post about Tynt – a service that lets you track copy/paste in their interface. I liked it, but I didn’t love it because:
- The hefty script added to my page load time
- It saved all the metrics in its own interface (which I never logged into)
- None of the metrics were visible within the context of all my other valuable analytics data
I just had to find a better solution…
Hunting for an Alternative
This annoyed me, so earlier this year I did some Googling and found an excellent jQuery solution on Onderweg. This script had everything I needed but it was missing a few things:
- I didn’t want another jQuery plugin to keep track of
- I wanted to track more than a handful of letters in the clipboard
- New lines and paragraphs were not represented at all
- The length of the copied string was never tracked
- The events were counted in the bounce rate calculation
- Page paths were not tracked inside the event – making some analyses difficult
Therefore, I hacked away at it, tailoring it to suit my needs. And this is what I came up with:
Tracking Copying to Clipboard in Google Analytics
Simply add this script after your GA script and jQuery library (Note – Requires jQuery and async version of the Google Analytics script):
<script type"text/javascript">
// Track copied content adapted from Onderweg & Tim Down by Robert Kingston - http://www.optimisationbeacon.com/
// Get Selection Text function by Tim Down - http://stackoverflow.com/a/5379408/458627
function getSelectionText() {
var e = "";
if (window.getSelection) {
e = window.getSelection().toString()
} else if (document.selection && document.selection.type != "Control") {
e = document.selection.createRange().text
}
return e
}
jQuery(document.body).bind("copy cut paste", function (e) {
var content = getSelectionText();
var contentClean = content.substring(0, 499).replace(/\\(n|r\\n|r)/gm, "\\n "); // Represent new lines
var length = content.length;
_gaq.push(['_trackEvent', 'clipboard', e.type+' location: '+document.location.pathname, contentClean, length, true]);
});
</script>This tracks copying from anywhere on the page, including line breaks and up to 500 characters of text. There’s room to copy much more (the POST to __utm.gif supports up to 8,192 bytes per request), but I figured, 500 chars should suit most purposes.
Hey, you can always bump this up, yourself.
There you have it! Easy as one, two three. Here’s what it’ll look like in the Google Analytics interface:

Whether they copied, cut or pasted is captured in the event action alongside the URL path.

Contents of the clipboard are captured in the event label.

Under event value you will find how many characters were copied at once.

… and for the sake of organisation, copy/paste/cut events will be filed under “clipboard”.
Just for the hell of it, here’s an example of the content people have copied from my site. No surprises, here – it’s code!

What sorts of applications would you use this for?
Let me know in the comments…


what a cool Idea!! thanks for sharing!
Rob,
In your case since a lot of people are copying code, it highlights real value you’re bring to the table.
I think in terms of outcomes from that, I’d be inclined to go back through your posts where you’ve provided code that people are copying and see if you can up the ante on what you’re delivering.
For example, it might be possible to turn some of your past code snippets into a jQuery plugins. You might consider doing that because then you’ve got a resource on your site, that will help build links to your site over and above the pure content itself, ultimately leading to better search engine performance.
Al.
Thanks guys, I’m flattered.
Alistair, thanks for the idea. I’ve been thinking about rolling together a round up post. Perhaps that’ll encourage me to review my earlier posts and tighten them up. Tracking of copy/pasting of scripts will certainly help with finding the most used scripts. Without this metric, my bounce rate is naturally too high to tell which posts are sticky.
I have one more interesting engagement metric which will be shared through a post scheduled for next week.
Hey Robert, great post, this is useful tracking!
I just wrote about loads of different ways to use Event Tracking (with a guide etc) but I didn’t think of this use.
Do you fancy dropping a quick summary of this method (+link) in the comments to help people use Event Tracking for even more things? I’m sure people reading my post will be very interested in this post too!
Sure, Anna… I’ll drop a summary of it in the comments for you.
Hi Rob,
Thanks for sharing this and the work involved in tweaking the code.
Cheers,
Alex
Thanks for the comment, Alex – it’s much appreciated. Let me know how you go and if you need any help with the setup of the script or analysis of the copy/cut/paste data in GA.
I am using Universal GA and the code is slightly different. I think I have to change “_gaq.push” to “ga”. However, it still doesn’t work.
Here is the code that I modified from you:
function getSelectionText() {
var e = “”;
if (window.getSelection) {
e = window.getSelection().toString()
} else if (document.selection && document.selection.type != “Control”) {
e = document.selection.createRange().text
}
return e
}
jQuery(document.body).bind(“copy cut paste”, function (e) {
var content = getSelectionText();
var contentClean = content.substring(0, 499).replace(/\\(n|r\\n|r)/gm, “\\n “); // Represent new
lines
var length = content.length;
ga(‘send’, ‘event’, ‘clipboard’, e.type+’ location: ‘+document.location.pathname, contentClean,
length, true);
});
What is wrong with it? Thanks!
I have added ” ; ” but it still doesn’t work
function getSelectionText() {
var e = “”;
if (window.getSelection) {
e = window.getSelection().toString();
} else if (document.selection && document.selection.type != “Control”) {
e = document.selection.createRange().text;
}
return e;
}
jQuery(document.body).bind(“copy cut paste”, function (e) {
var content = getSelectionText();
var contentClean = content.substring(0, 499).replace(/\\(n|r\\n|r)/gm, “\\n “); // Represent new
lines
var length = content.length;
ga(‘send’, ‘event’, ‘clipboard’, e.type+’ location: ‘+document.location.pathname, contentClean,
length, true);
});
still doesn’t work
Hi Siravut,
Try the following to get this working in Google Universal Analytics:
ga('send', 'event', 'clipboard', e.type+' location: '+document.location.pathname, contentClean,length, {'nonInteraction':1});
Be careful of the quotation marks used – sometimes WP changes the quotes to make it look “pretty”.
EDIT: Forgot to mention that the issue was the non-interaction hit parmeter. This is handled a little bit differently in Universal Analytics.
It still doesn’t work…I’m not sure why.
Would it be alright if you take at look at my website? It is http://desrupt.com/
I know there are not that many words but I am trying it out just in case.
Thanks!
Hi Siravut,
Just checked your site and it looks like it needs to run after the
element exists. You should try wrapping this in a $(document).ready() or any of the equivalents. Give that a go. If not, I’m always here to take a look.Thanks for bringing this issue to my attention. Unfortunately, I have only ever used this script in tag managers. I will update my instructions so others can ensure this tracking works.
Just like you said, I put the code near the end of the body and it works! Thanks so much!