Skip to content

Commit

Permalink
Merge pull request #317 from skial/ga_track_outbound_links
Browse files Browse the repository at this point in the history
Add outbound link tracking.
  • Loading branch information
skial authored Jun 25, 2016
2 parents 5380c56 + 4d92770 commit 5e9956f
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 63 deletions.
2 changes: 1 addition & 1 deletion all-html.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
INPUT="$@"
electron --enable-logging . -w 1920 -h 1080 --input "//$INPUT/index.html" --script ./script.js --outputDir "//bin" --show \
--scripts linkqueue.js font.characters.js sitemap.js checkmissing.js screengrab.js version.js
--scripts linkqueue.js checkmissing.js font.characters.js sitemap.js screengrab.js version.js
find $INPUT -name "*.html" | xargs -P 6 -n 1 htmlmin.sh
1 change: 1 addition & 0 deletions buildjs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
browserify ./node_modules/autotrack/lib/plugins/outbound-link-tracker.js > ./src/js/outbound-link-tracker.js
81 changes: 57 additions & 24 deletions electron-checkmissing/CheckMissing.hx
Original file line number Diff line number Diff line change
Expand Up @@ -28,47 +28,66 @@ class CheckMissing {
ipcRenderer = electron.ipcRenderer;

var head = cast window.document.getElementsByTagName( 'head' )[0];
//var script = window.document.querySelectorAll( 'head script[src*="haxe.io.js"]' )[0];
var tags:Array<Array<Dynamic>> = [
[{tag:'link', rel:'apple-touch-icon', sizes:'57x57'/*, href:"/apple-touch-icon-57x57.png"*/}, {href:"/apple-touch-icon-57x57.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'60x60'/*, href:"/apple-touch-icon-60x60.png"*/}, {href:"/apple-touch-icon-60x60.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'72x72'/*, href:"/apple-touch-icon-72x72.png"*/}, {href:"/apple-touch-icon-72x72.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'76x76'/*, href:"/apple-touch-icon-76x76.png"*/}, {href:"/apple-touch-icon-76x76.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'114x114'/*, href:"/apple-touch-icon-114x114.png"*/}, {href:"/apple-touch-icon-114x114.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'120x120'/*, href:"/apple-touch-icon-120x120.png"*/}, {href:"/apple-touch-icon-120x120.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'144x144'/*, href:"/apple-touch-icon-144x144.png"*/}, {href:"/apple-touch-icon-144x144.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'152x152'/*, href:"/apple-touch-icon-152x152.png"*/}, {href:"/apple-touch-icon-152x152.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'180x180'/*, href:"/apple-touch-icon-180x180.png"*/}, {href:"/apple-touch-icon-180x180.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'16x16'/*, href:"/favicon-16x16.png"*/}, {href:"/favicon-16x16.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'32x32'/*, href:"/favicon-32x32.png"*/}, {href:"/favicon-32x32.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'96x96'/*, href:"/favicon-96x96.png"*/}, {href:"/favicon-96x96.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'192x192'/*, href:"/favicon-192x192.png"*/}, {href:"/favicon-192x192.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'194x194'/*, href:"/favicon-194x194.png"*/}, {href:"/favicon-194x194.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'manifest'/*, href:"/manifest.json"*/}, {href:"/manifest.json?v=wAANbdxLQn"}],
[{tag:'link', rel:'mask-icon', color:"#fffdf9", /*href:"/safari-pinned-tab.svg"*/}, {href:"/safari-pinned-tab.svg?v=wAANbdxLQn"}],
[{tag:'link', rel:'shortcut icon'/*, href:"/favicon.ico"*/}, {href:"/favicon.ico?v=wAANbdxLQn"}],
var body = cast window.document.getElementsByTagName( 'body' )[0];

var headTags:Array<Array<Dynamic>> = [
[{tag:'link', rel:'apple-touch-icon', sizes:'57x57'}, {href:"/apple-touch-icon-57x57.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'60x60'}, {href:"/apple-touch-icon-60x60.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'72x72'}, {href:"/apple-touch-icon-72x72.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'76x76'}, {href:"/apple-touch-icon-76x76.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'114x114'}, {href:"/apple-touch-icon-114x114.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'120x120'}, {href:"/apple-touch-icon-120x120.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'144x144'}, {href:"/apple-touch-icon-144x144.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'152x152'}, {href:"/apple-touch-icon-152x152.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'apple-touch-icon', sizes:'180x180'}, {href:"/apple-touch-icon-180x180.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'16x16'}, {href:"/favicon-16x16.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'32x32'}, {href:"/favicon-32x32.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'96x96'}, {href:"/favicon-96x96.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'192x192'}, {href:"/favicon-192x192.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'icon', type:"image/png", sizes:'194x194'}, {href:"/favicon-194x194.png?v=wAANbdxLQn"}],
[{tag:'link', rel:'manifest'}, {href:"/manifest.json?v=wAANbdxLQn"}],
[{tag:'link', rel:'mask-icon', color:"#fffdf9"}, {href:"/safari-pinned-tab.svg?v=wAANbdxLQn"}],
[{tag:'link', rel:'shortcut icon'}, {href:"/favicon.ico?v=wAANbdxLQn"}],
[{tag:'meta', name:'msapplication-TileColor', content:"#f15922"}, {}],
[{tag:'meta', name:'msapplication-TileImage'/*, content:"/mstile-144x144.png"*/}, {content:"/mstile-144x144.png?v=wAANbdxLQn"}],
[{tag:'meta', name:'msapplication-TileImage'}, {content:"/mstile-144x144.png?v=wAANbdxLQn"}],
[{tag:'meta', name:'theme-color', content:"#ffffff"}, {}],
[{tag:'script', src:'/js/haxe.io.js'}, {async:'async', defer:'defer'}],
[{tag:'script', src:'/js/outbound-link-tracker.js'}, {async:'async', defer:'defer'}],
[{tag:'script', type:'text/javascript'}, {innerHTML:"(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','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-49222122-1', 'auto');
ga('require', 'displayfeatures');
ga('require', 'outboundLinkTracker');
ga('set', 'forceSSL', true);
ga('send', 'pageview');"}],
];

for (array in tags) {
var bodyTags:Array<Array<Dynamic>> = [
//[{tag:'a', href:'://'}, {onclick:"trackOutboundLink('http://www.example.com'); return false;"}]
];

for (array in headTags) {
var keys:DynamicAccess<String> = array[0];
var values:DynamicAccess<String> = array[1];
var selector = keys.get('tag') + [for(key in keys.keys()) if (key != 'tag') '[$key*="${keys.get(key)}"]'].join('');
var selector = keys.get('tag') + [for(key in keys.keys()) if (key != 'tag' && key != 'innerHTML') '[$key*="${keys.get(key)}"]'].join('');
var matches = window.document.querySelectorAll( selector );

if (matches.length == 0) {
var element:DOMElement = window.document.createElement( keys.get('tag') );
for (key in keys.keys()) if (key != 'tag') element.setAttribute( key, keys.get( key ) );
for (key in keys.keys()) if (key != 'tag' && key != 'innerHTML') element.setAttribute( key, keys.get( key ) );
for (key in values.keys()) element.setAttribute( key, values.get( key ) );
if (values.exists('innerHTML')) element.innerHTML = values.get('innerHTML');
cast(head,Node).appendChild( element );

} else {
var element = cast(matches[0],DOMElement);
if (element.hasAttribute('contents')) element.removeAttribute('contents');
if (element.hasAttribute('tag')) element.removeAttribute( 'tag' );
for (key in values.keys()) if (key != 'tag') element.setAttribute( key, values.get( key ) );
for (key in values.keys()) if (key != 'tag' && key != 'innerHTML') element.setAttribute( key, values.get( key ) );
if (values.exists('innerHTML')) element.innerHTML = values.get('innerHTML');
for (i in 1...matches.length) {
head.removeChild( matches[i] );
}
Expand All @@ -77,6 +96,20 @@ class CheckMissing {

}

for (array in bodyTags) {
var keys:DynamicAccess<String> = array[0];
var values:DynamicAccess<String> = array[1];
var selector = keys.get('tag') + [for(key in keys.keys()) if (key != 'tag') '[$key*="${keys.get(key)}"]'].join('');
var matches = window.document.querySelectorAll( selector );

if (matches.length > 0) for (match in matches) {
var element = cast(match,DOMElement);
for (key in values.keys()) if (key != 'tag') element.setAttribute( key, values.get( key ) );

}

}

ipcRenderer.send('checkmissing::complete', 'true');

}
Expand Down
71 changes: 37 additions & 34 deletions electron-version/Version.hx
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,33 @@ using StringTools;
using haxe.io.Path;

class Version {

private var electron:Dynamic;
private var ipcRenderer:{on:String->Function->Dynamic, once:String->Function->Dynamic, send:String->Rest<Dynamic>->Void};
private var hashedPaths:StringMap<String> = new StringMap();
private var input:String = '';
private var counter:Int = 0;

public static function main() {
var v = new Version();
}

public function new() {
electron = require('electron');
ipcRenderer = electron.ipcRenderer;

ipcRenderer.send('fetch::data', 'version');
ipcRenderer.on('fetched::data::version', function(event:String, arg:String) {
var data:{input:String} = Unserializer.run(arg);
if (data.input != null) input = data.input;
for (node in window.document.querySelectorAll( 'link[href]' )) process('href', cast node);
for (node in window.document.querySelectorAll( 'body [src], script[src]' )) process('src', cast node);
for (node in window.document.querySelectorAll( 'meta[content*="ms"]' )) process('content', cast node);

});

}

private function process(attr:String, node:DOMElement):Void {
var value:String = node.getAttribute( attr );
trace( value );
Expand All @@ -59,14 +59,14 @@ class Version {
if ((url.query:DynamicAccess<String>).exists('v')) {
Reflect.deleteField(url, 'search');
(url.query:DynamicAccess<String>).remove('v');

}

value = format( url );
trace( format(url).normalize() );
var cb = modifyUrl.bind(node, attr, _, _);
hash('content::hash', format(url).normalize(), cb);

} else {
if (url.host != null && url.host.indexOf('haxe.io') > -1) {
counter++;
Expand All @@ -75,50 +75,50 @@ class Version {
if ((url.query:DynamicAccess<String>).exists('v')) {
Reflect.deleteField(url, 'search');
(url.query:DynamicAccess<String>).remove('v');

}
url.protocol = url.hostname = url.host = '';
trace( format(url).normalize() );
hash('content::hash', format(url).normalize(), cb);

}

}
}

private function modifyUrl(node:DOMElement, attr:String, event:String, arg:String):Void {
if (arg != 'failed'){
var value:String = node.getAttribute( attr );
var url = parse( value, true, true );

Reflect.deleteField(url, 'search');
if (url.query == null) url.query = {};
if ((url.query:DynamicAccess<String>).exists('v')) {
Reflect.deleteField(url, 'search');
(url.query:DynamicAccess<String>).remove('v');

}
(url.query:DynamicAccess<String>).set('v', arg);
//trace( format( url ) );
node.setAttribute( attr, format( url ));

} else {
trace( event, node.getAttribute(attr) );
trace( event, arg, node.getAttribute(attr) );
}

counter--;
//trace( counter );
if (counter < 1) ipcRenderer.send('version::complete', 'true');
}

private function hash(event:String, arg:String, cb:String->String->Void):Void {
var path = (__dirname + input.directory() + arg).normalize();
//trace( path.extension() );
if (path.extension() == '') path += '/index.html';
//trace( path );
trace( path );
if (hashedPaths.exists(path)) {
cb('content::hashed::$arg', hashedPaths.get( path ));

} else {
stat(path, function(error, stats) {
if (error == null && stats.isFile()) {
Expand All @@ -128,30 +128,33 @@ class Version {
var data = stream.read();
if (data != null) {
hash.update(data);

} else {
hashedPaths.set( path, hash.digest('hex') );
var digest = hash.digest('hex');

hashedPaths.set( path, digest );
//try {
//trace( hashedPaths.get( path ));
cb('content::hashed::$arg', hashedPaths.get( path ));
cb('content::hashed::$arg', digest);

/*} catch (e:Dynamic) {
console.log( path, hashedPaths.get( path ), e );
}*/

}
});

} else {
trace( error );
cb('content::hashed::$arg', 'failed');

}

});

}

}

}
2 changes: 1 addition & 1 deletion htmlmin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,5 @@ cp $MIN $OPT
html-minifier \
--collapse-boolean-attributes --remove-comments --remove-empty-attributes --remove-redundant-attributes \
--collapse-whitespace --decode-entities --minify-js --remove-style-link-type-attributes \
--remove-script-type-attributes --minify-css -o $OPT $OPT_CRIT
--remove-script-type-attributes --minify-css -o "$OPT" "$OPT_CRIT"
#zopfli --i1000 $OPT
32 changes: 32 additions & 0 deletions jsmin.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
CLOSURE=./node_modules/google-closure-compiler/compiler.jar
INPUT="$@"
#echo $INPUT
STR="${INPUT:3}"
BIN=./bin$STR
BIN_DIR=${BIN%/*}
BIN_BASE="${BIN/$BIN_DIR/}"
BIN_BASE="${BIN_BASE/.css/}"

MIN=./min$STR
MIN_DIR=${MIN%/*}
MIN_BASE="${MIN/$MIN_DIR/}"
MIN_BASE="${MIN_BASE/.js/}"

OPT=./opt$STR
OPT_DIR=${OPT%/*}
OPT_BASE="${OPT/$OPT_DIR/}"
#echo $BASE
OPT_BASE="${OPT_BASE/.js/}"
OPT_CRIT=$OPT_DIR$OPT_BASE.crt.js
OPT_TWIN=$OPT_DIR$OPT_BASE.opt.js

mkdir -p $BIN_DIR
mkdir -p $MIN_DIR
mkdir -p $OPT_DIR

cp $INPUT $BIN
cp $BIN $MIN
cp $MIN $OPT

java -jar $CLOSURE --js $INPUT --compilation_level SIMPLE_OPTIMIZATIONS --js_output_file $BIN
java -jar $CLOSURE --js $INPUT --compilation_level ADVANCED_OPTIMIZATIONS --js_output_file $OPT
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"name": "haxe.io",
"repo": "https://github.com/skial/haxe.io",
"version": "0.0.1",
"devDependencies": {
"onchange": "latest",
"http-server": "latest",
Expand All @@ -12,11 +14,15 @@
"critical": "addyosmani/critical",
"node-static": "latest",
"electron-prebuilt": "latest",
"electron-spawn": "latest"
"electron-spawn": "latest",
"browserify": "latest",
"autotrack": "latest",
"google-closure-compiler": "latest"
},
"scripts": {
"scripts": {
"watch:jsmin": "onchange \"./src/js/*.js\" -w -- jsmin.sh {{changed}}",
"watch:htmlmin": "onchange \"./src/**/*.html\" -w -- htmlmin.sh {{changed}}",
"watch:cssmin": "onchange \"./src/css/*.css\" -w -- cssmin.sh {{changed}}",
"watch": "npm-run-all -p watch:cssmin watch:htmlmin"
"watch": "npm-run-all -p watch:jsmin watch:cssmin watch:htmlmin"
}
}

0 comments on commit 5e9956f

Please sign in to comment.