Tracking Clicks in Emails to 3rd Party Websites - email

A hopefully simple GA newbie question.
I programmatically (in Java) send emails to my clients and I'm trying to track what links in the email they click.
The links in the emails are to third party websites.
Is there a way to setup the href links so that I can track what uid's are clicking and treat clicking those links as an event?
An example link would be to a piece of legislation:
https://www.cga.ct.gov/asp/cgabillstatus/cgabillstatus.asp?selBillType=Bill&which_year=2017&bill_num=5210
how would I add that link in the email HTML?

That does not work, at least not with additional resources.
Google Analytics tracks links by sending a request to the Google servers before the user is redirected to the link href. In web tracking this is usually done via a javascript event handler that is attached to the link. In e-mail javascript is not really an option, so that does not work.
What is usually done instead is that in your emails you link to your own server; there is a script that collects the data from the link, and only then it redirects to the originally requested url. Most commercial newsletter packages integrate a solution like that, but you can set up something yourself with some basic programming skills and the Google Analytics measurement protocol (which would allow you to send tracking calls from a server-side redirection script).

Setup the Redirects Tracking Engine
The Redirects Tracking Engine makes it easy to collect event data where traditional tracking methods may not have been possible. This tracking engine utilizes Google Tag Manager and Google Analytics to capture events and is run on the client side. All events can be seen in Google Analytics (Behavior > Events > Top Events).
Getting Started
Installation
Add the latest JQuery and Redirects Tracking Engine scripts to the header of your site.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script><script type="text/javascript">// Fetches redirects.txt and stores information in the variable data
$.get('redirects.txt', function(data) {
// Fetches the parameters of the query string and stores the path in urlParams
var urlParams = [];
// Sifts through the string and removes unwanted characters
(function () {
var match,
pl = /\+/g, // Regex for replacing addition symbol with a space
search = /([^&=]+)=?([^&]*)/g,
decode = function (s) { return decodeURIComponent(s.replace(pl, '')); },
query = window.location.search.substring(1);
while (match = search.exec(query))
urlParams[decode(match[1])] = decode(match[2]);
})();
// Pulls properties from urlParams and stores them in destination array
var destination = Object.keys(urlParams).map(function(path){return urlParams[path]});
// Assigns the redirects.txt data to the userData array
var userData = data.split('\n');
// Multidimensional array declaration
var redirects = [];
// Fetches the total number of objects in the userData array
var total = userData.length;
// Counter variable
var i = 0;
// Runs through the redirects array to check to see if there is a string match
while (i < total) {
// Places userData into the multidimensional redirects array
redirects[i] = userData[i].split(' => ');
// Checks for a path match in the redirects array
if (redirects[i][0] == destination[1]) {
window.location.href = redirects[i][1];
return;
}
i++;
}
// Redirects to safe page if no match is found
window.location.href = 'https://example.com';
});
Setup Google Tag Manager
Paste this code as high in the <head> of the page as possible. Make sure to substitute the filler GTM-XXXX with your Google Tag Manager Account ID.
<!-- Google Tag Manager --><script>(function(w,d,s,l,i){w[l]=w[l]|| [];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js? id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXX');</script>
<!-- End Google Tag Manager -->
Additionally, paste this code immediately after the opening <body> tag. Make sure to substitute the filler GTM-XXXX with your Google Tag Manager Account ID here as well.
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
NOTE: For more information about installing the Google Tag Manager snippet, check out their Quick Start Guide.
Create Tags/Triggers/Variables
Create a variable — You will need to first create a User-Defined Variable. Go to the Variables page of your Google Tag Manager and in the User-Defined Variables section create a new variable named Tracking ID. Give this variable your Google Analytics Tracking ID in the Value field and SAVE.
Create a tag — You will need to go to the Tags page in Google Tag Manager and click the NEW button. Fill in the fields and click SAVE when finished.
Create a trigger — Finally, you will need to create a trigger. Go to the Triggers page in Google Tag Manager. Once there click on the NEW button and fill in the fields and click SAVE when finished.
After these configurations have been setup in Google Tag Manager you are ready to add your redirects to the redirects.txt file.
Redirects
To add a redirect open the redirects.txt file. The text linkedin is telling the engine what path it needs to look for in the URL. Immediately following is the separator => which shows the engine where the assigned path should direct the user. New redirects can be added on a new line and there are no limits to the number of redirects that can be added to this file.
// Example Redirect
linkedin => https://example.com
Failsafe
In the off-chance that one of the redirects is not working it is good to have a page that the user can be directed to. You can add in your failsafe page by modifying the window.location.href location that comes immediately after the loop.
// Redirects to safe page if no match is found
window.location.href = 'https://example.com';
Browser Support
Supported Browsers : Chrome, Firefox, Safari, Opera, Edge, IE7+.
The source code as well as an example can be found on GitHub.

Related

How to retrieve the Query string value from web word instance

I'm creating a web add-in for Word targeting Word Online. When a document is opened using Word Online, the URL will contain a file name. I am trying to retrieve that file name.
To retrieve this URL I tried using window.location href, but it is fetching my hosted addin web application URL. Is it possible to get the Word Online URL?
Sample Code :
function getParameterByName(name, url) {
if (!url) url = window.location.search;
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
What you should use instead?
You should use Office.js API that's defined here
https://learn.microsoft.com/en-us/javascript/api/office/office.document
Office.context.document.url this should return you something that you can use.
Why didn't your solution work?
Unfortunately this is not possible the way you're trying to implement it due to security requirements around iFrames. Word Online is using an iFrame to host your add-in and accessing the parent window from an iFrame is generally very restricted unless you're specifically allowed.
You can however get the base host url of the parent window by looking into the referrer header, but that's pretty much it. I understand that this is not sufficient for you, which is why I'm recommending to use the Word API.
You can see a bit more documentation below about iFrames:
iFrame spec documentation: https://www.w3.org/TR/2011/WD-html5-20110525/the-iframe-element.html
On getting the url that's loading the frame (the parent URL): https://humanwhocodes.com/blog/2013/04/16/getting-the-url-of-an-iframes-parent/
Some more information on how to communicate between parent and the iFrame using postMessage API if you were whitelisted (which you aren't): https://medium.com/#Farzad_YZ/cross-domain-iframe-parent-communication-403912fff692

Sitelock .unity3d

I had done some modifications to unity games (like infinite ammo, player invincible) using .net reflector thru reflexil plugin & hosted on my domain.
Can I sitelock .unity3d files to my domain & how
You should be able to check the domain in the code (best result check in the first scene) so that if it not on your chosen URL then then can do a different action (i.e. redirect, display a message)
This manual page
should show what you need and
Application.ExternalEval("if(document.location.host != 'YOURDOMAIN.COM') { document.location='WHERE_TO_REDIRECT_YOUR_USER; }");
will push them back to your site each time. You could increase this to report back to you as well and you would have a log of sites hosting incorrectly it required.
I wrote a script that will "lock your Unity3D game to a specific list of websites."
An updated version is also available on GitHub and also, identically on Bitbucket
From the readme.md
A C# script for Unity 3D that prevents your Web Player project from running on
websites that are not authorised.

You may also need to check that the game is not embedded in another site using an iframe.
When dealing with frames you can't access a page from a different domain.
This actually means we don't even need to check the host of the outer page, because if we can even access it then we know it's from the same domain anyway.
So this will redirect someone if your page is not being embedded in a page with the same host:
Application.ExternalEval(
"if(parent && parent.document == undefined)
{
window.top.location.replace('http://goo.gl/9ulDD');
}"
);
If you really do need to check the exact URL (for example, you're hosting the page on foo.com and you want bar.com to be able to embed your content) then you can check the document.referrer, which is set to the URL of the page that includes the frame:
Application.ExternalEval(
"if (parent)
{
var pathParts = document.referrer.split('/');
if (pathParts[2] != '" + locktoSite + "')
window.top.location.replace('http://goo.gl/9ulDD');
}"
);

How to get url of a tab before the page gets loaded in Mozilla Addon SDK?

I am creating an addon for blocking sites on user request.I have done- getting user input and storing in simple-storage.Now i want to access the url of the tab(s) before the page gets loaded so that i can process the url and gets it hostname to block the site.
You do this using the PageMod module with onAttach.
pageMod.PageMod({
contentScriptWhen: 'start', //This says not to wait until the page is ready
include: ['*'],
//Forget about contentScript(File), we're not attaching a script
onAttach: function(worker) {
var tabUrl = worker.tab.url;
if(tabUrl==myString) worker.tab.url = 'http://arabcrunch.com/wp-content/uploads/2013/05/block-website.jpeg'
}
});
But I recommend doing it differently. Instead of checking every URL yourself then doing something , you create an array of URLs or partial URLs and set include: myArrayOfUrls. Then you don't need the if clause in onAttach, you already know that it's one of the websites you want to block.
You can register to the http-on-modify-request notification from the Observer Service. You'll get notified just before the request is made and you can get the URL.
See the following resources on the topic:
Setting HTTP request headers for registration example and Observer Notifications for the list of notifications you can register to.
What you describe is essentially what the Adblock Plus extension is doing, maybe you could use it directly or look into its code.

Fetch and display Google Doc body within html page

Is it possible to retrieve the content of a Google Doc and display it within a div in an html page? If so, what's the right way to implement the "MAGIC" in the stripped-down example below?
<html>
<head>
</head>
<body>
<div>
<MAGIC>
Script or link that retrieves and displays the body of a Google Doc.
</MAGIC>
</div>
</body>
</html>
In the above, you can assume
The html is served by Google Drive Hosting.
The reference to the Google Doc is static.
There is no need to edit the Doc from within the public html page (i.e it's read-only in that context).
I've read through the Apps Script documentation and it looks as though something might be possible with some combination of Document Service and Content Service. For instance, Document Service has getBody() and copy() methods, but it's not clear whether the objects returned by these calls can be rendered WYSIWYG as html for insertion into an html container.
Background: I'm trying to implement a safe easy-to-use CMS for a small nonprofit. I've prototyped a website framework that's hosted
on Google Drive. So far it looks promising, but changes require being able to edit the html. We have a number of people who can create content in a word-processor-like environment but only couple including myself
who can cope with HTML/CSS/JQuery/AppsScript.
If I could concentrate on the overall framework and let the others update the content for
events, etc., that would be a huge win. Basically, I'd be very happy if they were able to edit the Google Doc and then manually reload the web page to see the result.
I realize there are many approaches for CMS, but for now, I'm interested in exploring a pure Google Docs/Google Drive solution.
I've settled on publishing the content docs and including the iframe embed code supplied by Google to implement the "MAGIC" from my original question, e.g
<iframe class="cmsframe" src="https://docs.google.com/document/d/1rhkuAB3IIu5Hq0tEtA4E_Qy_-sJMMnb33WBMlAEqlJU/pub?embedded=true"></iframe>
The class tag is added manually so I can control the iframe size with CSS.
You can get the raw html content of a google doc with a call to the drive API using urlFetch, here is how it works
var id = 'Doc-Very-Long-ID-Here';
var url = 'https://docs.google.com/feeds/';
var doc = UrlFetchApp.fetch(url+'download/documents/Export?exportFormat=html&format=html&id='+id,
googleOAuth_('docs',url)).getContentText();
// the variable doc is the HTML content that you can use
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
There is also a library by Romain Vialard available here it is called DocsListExtended and provides a whole bunch of nice extensions.
EDIT : Following your EDIT:
You can't use it just like that, to render an HTML content in a webapp use html service, example below with your complete code and working example:
function doGet() {
var id = '1el3DpTp1sukDjzlKXh8plf0Zj-qm0drI7KbytroVrNU';
var url = 'https://docs.google.com/feeds/';
var doc = UrlFetchApp.fetch(url+'download/documents/Export?exportFormat=html&format=html&id='+id, googleOAuth_('docs',url)).getContentText();
return HtmlService.createHtmlOutput(doc);
}
// the variable doc is the HTML content that you can use
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:name, oAuthUseToken:"always"};
}

Redirecting to second page in GWT doesn't load GWT components in second page

i am using GWT app engine to deploy my application in local host.
i want to redirect to second page when user completed his registration & clicked "submit" button, the browser has to redirect to automatically to his Profile page with his registration details.
i used fallowing code to redirect to second page from first page;
String url = GWT.getHostPageBaseURL()+"/UserViewProfile.html";
Window.Location.replace(url);
in my case the first page is URL is like:
http://127.0.0.1:8888/UserRegistration.html?gwt.codesvr=127.0.0.1:9997
when i submitted on "Submit" button it is edirecting to URL like:
http://127.0.0.1:8888/UserViewProfile.html
In second page(UserViewProfile.html) i developed simple HTML content & simple Textbox widget to check it's functionality. But i am seeing HTML content only but not "Textbox".
To see text box i has to type URL like:
http://127.0.0.1:8888/UserViewProfile.html?gwt.codesvr=127.0.0.1:9997
how i can access last part "?gwt.codesvr=127.0.0.1:9997" at end of my URL pattern automatically? if i add it manually, at the time of hosting it may leads to problem. please if any body give solution, that would be great.
I do not understand the use case. Anyway I guess you need to conditionally check if you are in DevMode or ProdMode, and add the gwt.codesvr=127.0.0.1:9997 query string accordingly. Something like:
String url = GWT.getHostPageBaseURL()+ "/UserViewProfile.html";
if (GWT.isProdMode()) {
Window.Location.replace(url);
} else {
Window.Location.replace(url + "?gwt.codesvr=127.0.0.1:9997");
}
The gwt.codesvr=127.0.0.1:9997 query string parameter is used by GWT to (simplifying) bootstrap your app in the so called Development Mode, instead of the Production Mode (the actual compiled version of your application). Without this check, if you are in DevMode, you end up requesting the UserViewProfile.html that looks for the compiled version of your app (that does not show anything, if you've never compiled it, or if you have simply recently clean the project).
Do also note that URL rewriting (by not simply changing the # fragment identifier), means application reloading.