How to change the application favicon in runtime? - gwt

I need to change the favicon depending on brand in runtime. When application starts I call webservice to establish the brand and then I need to configure the application. I don't know how to update favicon - is it possible?
<link rel="shortcut icon" href="favicon-brand1.ico">
To clarify the background of my need - my application is a GWT application, the requirement is to configure its appearance depending on domain name (brand) before it completes loading. So I have implemented web service which gives me all configuration data like site name, site description (placed in host HTML page in meta description) and associated favicon.
I was able to update meta tags of my app but I couldn't find a solution how to update app's icon from GWT code instead of using JavaScript code.

You can access any tag on your host page.
So something like this should work:
NodeList<Element> nodes = Document.get().getElementsByTagName("link");
for (int i = 0; i < nodes.getLength(); i++) {
LinkElement link = LinkElement.as(nodes.getItem(i));
if (link.getRel("shortcut icon") != null) {
link.setHRef("favicon-brandNew.ico");
}
}

Well not sure of the context of your application but I'd imagine if you have this generated dynaically the right thing would just happen.
By this I mean specify the file name in a model property and use that in the view.
So, don't hard code it - look it up.
So you'd end up with somethiong along the lines of....
<link rel="shortcut icon" href="#model.BrandFavIcon">

Related

Unable to fetch page properties in the head script

I am trying to get a page property in the head of my page basically to make it universally available so that the front end developers can use it in their scripts as they will.
This is on AEM 6.3. And I've already tried to include a script in the head.html but it can't read the page properties in a script tag.
<script>
window.myAppEndpoint = {
baseURL: "${properties.myappendpoint}"
};
</script>
I expect the window object to populate with my endpoint value be able to use it anywhere in the application.
You should be able to do this provided:
The myappendpoint property is defined for the page jcr:content node
You are using the proper display context: baseURL: "${properties.myappendpoint # context='uri'}"
You can create a global object in js and include that js in the clientlib at the template level.
Or use the global objects available in HTL. Please have a look here.

Tracking Clicks in Emails to 3rd Party Websites

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.

Rendering pictures in email's template in Meteor

I have and nice email template stored in /private folder and I have some pictures in /public/images folder. I have img tags with links to my template using full path (http://localhost:3000/images/image1) or external links.
I render my template using
SSR.compileTemplate('myTemplate',Assets.getText('myTemplate.html');
renderedTemplate = SSR.render('myTemplate',emailData);
var dataContext = {
htmlHead: '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">',
htmlFoot: '</html>'
};
and then I use
finalHtml = dataContext.htmlHead + renderedHtml + dataContext.htmlFoot;
Email.send({
from: smtp.login,
to: email,
subject: 'News',
html: finalHtml
});
Then when I get my lovely mail everything is nice and perfect but my attached images which are not loaded;is it a problem with SSR.compileTemplate? Usually static pictures should be attached at the bottom of email (if I check the "show original" in my gmail) but they are not there..
What am I doing wrong and how I should solve it?
Using the Meteor.absoluteUrl method is the proper way to reference an image source. However, I believe you will still face the same problem even after using it.
This is because you are trying to reference an image from a non-publicly accessible url. Which in your case localhost will be the host in your full path to your image. Your html template needs to reference the images to a specific uri. In this case, it won't be able because it's been hosted on your local machine.
If you deploy your app on a hosted environment, your host url will be served up. Hope that makes sense.
Try using Meteor.absoluteUrl, see docs here.
Maybe something like:
emailData.absoluteUrl = Meteor.absoluteUrl('/');
Then in your template:
<img src="{{absoluteUrl}}/path-to-your-image.jpg"/>
Haven't tried it myself, so this is untested. I tend to use assets direct from S3.

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"};
}

app_offline.htm file does not work

I have been battling with this for ages now but I just can not get it to work.
Every blog/site I have been too says there is nothing you need to do in IIS but this cannot be correct as there are multiple website configurations such as Application, virtual directory, simple php/asp websites, vitual.
Can someone please explain to me what the setup needs to look like in IIS7.
I have:
Checked the file spelling: app_offline.htm
Made sure the file was at least 512 bytes (saw this on a random site)
Made sure it is in fact in the root of the application/website
Checked that I can browse directly to the file
Made sure the application pool framework was set to v2.0 or v4.0
Made sure the above application pool was assigned to my website
Tried this in a new website in IIS where the app_offline.htm was the only file in the root.
I have multiple websites set up that I have tested with, namely:
MVC3 Web Application
PHP Simple Website
Classic ASP Simple Website
Webforms Website
Webforms Application
Virtual folders in the above sites
Applications within the above sites
All of the above are working, and placing the app_offline.htm does absolutely nothing.
Please can someone provide some clarity.
I recently had the same issue with the app_offline file and the real problem I had was that windows was set to hide known file extensions. So when the file app_offline.htm was created I thought that the name was correct, but windows was hiding the extension .txt.
Create a web.config file with following content
<?xml version="1.0"?>
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
</configuration>
Hope that helps.
I was also struggling a little bit with this issue.
Along with the fore-mentioned criteria in the other answers. It turns out that the file type MUST be specified specifically .htm NOT .html.
I had the same issue, and although I couldn't solve it, I found a reasonable workaround. I added the same file, but named "appoffline.htm" to the root directory and leave it there permanently.
When I need to take application offline, I use the IIS HTTP Redirection setting for the website to redirect all incoming requests to appoffline.htm (make sure to tick "Redirect all requests to exact destination").
So I never did find a solution to this problem but I did find an alternative to what I was trying to achieve.
Basically, I wanted to show a specific "offline" page per app which would show when the site was offline. Here is what I did...
I created a website I called "_offline" in IIS. I then added a generic "catch all" binding for Port: 80 and left the host name blank. You may need to disable your current default website before this binding will be accepted.
Create an index.html page and put whatever content in there you want to show and shove it as the default page for "_offline". I'll include a bit of script below that works pretty well.
Now you can test by turning off your website, you should see your new index page. If you can't turn off the website, add a binding in your hosts file to anything like "testdomain.com" and point that to your server. Entering that in your browser should then show your offline page.
Just bare in mind, this page will show any time your IIS can not find an active website at the address coming in. Depending on your setup, this may or may not be acceptable in which case you should not use this method.
Now for my index page. I put some javascript in to determine which site the user is trying to reach, then reveal a portion of the html. I also have a countdown that runs and tries to refresh the page every 10 seconds.
Anyway, not the ideal result, but it works.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width = device-width">
<title>Under Maintenance</title>
</head>
<style>
body{
color:#014795;
}
.container{
max-width:650px;
margin:auto;
font-size:18px;
font-family:Arial, Helvetica, sans-serif;
padding:20pt;
text-align:center
}
#logo img {
max-width:100%;
}
a {
color: inherit;
text-decoration: none;
}
a:hover {
color: inherit;
text-decoration: none;
}
</style>
<body>
<table class="container">
<tr>
<td>
<span id="logo"></span>
<p>This site is currently under maintenance and will be available shortly.</p>
<p>We apologize for any inconvenience caused.</p>
<table style="text-align:left;margin:auto;">
<tr><td>Telephone:</td><td>+27 11 11 1111</td></tr>
<tr><td>Fax:</td><td>+27 11 111 2222</td></tr>
<tr><td>Email:</td><td>support#fubar.com</td></tr>
</table>
<p>We will automatically try to reconnect you in <span id="timeleft"></span> seconds</p>
</td>
</tr>
</table>
<script type="text/javascript">
var refreshEvery = 10;
var currentSec = 0;
var timer = setInterval(function() {
currentSec++;
if (currentSec >= refreshEvery) {
clearInterval(timer);
location.reload();
}
document.getElementById("timeleft").innerHTML = "" + (refreshEvery - currentSec);
}, 1000)
document.getElementById("timeleft").innerHTML = "" + (refreshEvery - currentSec);
// Use this site to create a base64 image http://www.base64-image.de/step-1.php
if (document.domain.indexOf("stacksnippets") >= 0) {
// Cusomise the site here, you can also show hide html content.
document.body.style.backgroundColor = "black";
document.body.style.color = "white";
} else {
// put default stuff here
}
</script>
</body>
</html>
Try to start out with a fresh and simple app_offline.htm file, like
<html><body>offline</body></html>
to see if that fixes the problem. In my case the problem was that the file encoding of the app_offline.htm file was "UTF-8 with BOM" rather than plain UTF-8.
The following handler also needs to be present:
ExtensionlessUrlHandler-Integrated-4.0
Make sure that in IIS Manager, on the website's Properties, the Application name has been created. Properties > Directory > Application settings > Application name.
Tested in IIS V6.0
None of the solutions above worked for us.
When testing on the server with same file but renamed (app_offline.TEMPLATE.htm) the server loaded the htm page without issue.
This was resolved by removing the large-ish Base64 encoded image from the file. (used as a background-image)
The app_offline.htm file still uses a Base64 encoded favicon and company logo image.