SlideShare a Scribd company logo
1 of 44
Spicy Javascript
Alban Gérôme
@albangerome
MeasureCamp London
11 July 2020
Your first Chrome Extension for Web Analytics QA
Why a Chrome Extension?
• Intercept, block, redirect, report all web requests
• Inject Javascript code anywhere, any time of the page
• Surface all the analytics tracking on the current web
page
Why a Chrome Extension?
• Inject code on the page locally without speaking to a
single web developer before the page has even
finished rendering
• Surface deep internal Adobe Launch rules information
• Report the information using little-known Javascript
console tricks
The Four Elements
• Manifest file
• Content script
• Popup script
• Background script
mandatory metadata
runs on the current page
runs in the extension popup
invisible broker
Manifest
{
"name": "Duckface",
"version": "1.1",
"manifest_version": 2,
"description": "Adobe Launch Debugger",
"browser_action": {
"default_icon": "duckface-icon.png",
"default_popup": "duckface2.html"
},
"permissions": [
"webRequest",
"<all_urls>",
"activeTab"
],
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content2.js"],
"run_at": "document_start"
}],
"background": {
"persistent": true,
"scripts": [
"background2.js"
]
}
}
Manifest
{
"name": "Duckface",
"version": "1.1",
"manifest_version": 2,
"description": "Adobe Launch Debugger",
"browser_action": {
"default_icon": "duckface-icon.png",
"default_popup": "duckface2.html"
},
"permissions": [
"webRequest",
"<all_urls>",
"activeTab"
],
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content2.js"],
"run_at": "document_start"
}],
"background": {
"persistent": true,
"scripts": [
"background2.js"
]
}
}
Manifest
{
"name": "Duckface",
"version": "1.1",
"manifest_version": 2,
"description": "Adobe Launch Debugger",
"browser_action": {
"default_icon": "duckface-icon.png",
"default_popup": "duckface2.html"
},
"permissions": [
"webRequest",
"<all_urls>",
"activeTab"
],
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content2.js"],
"run_at": "document_start"
}],
"background": {
"persistent": true,
"scripts": [
"background2.js"
]
}
}
Manifest
{
"name": "Duckface",
"version": "1.1",
"manifest_version": 2,
"description": "Adobe Launch Debugger",
"browser_action": {
"default_icon": "duckface-icon.png",
"default_popup": "duckface2.html"
},
"permissions": [
"webRequest",
"<all_urls>",
"activeTab"
],
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content2.js"],
"run_at": "document_start"
}],
"background": {
"persistent": true,
"scripts": [
"background2.js"
]
}
}
Manifest
{
"name": "Duckface",
"version": "1.1",
"manifest_version": 2,
"description": "Adobe Launch Debugger",
"browser_action": {
"default_icon": "duckface-icon.png",
"default_popup": "duckface2.html"
},
"permissions": [
"webRequest",
"<all_urls>",
"activeTab"
],
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content2.js"],
"run_at": "document_start"
}],
"background": {
"persistent": true,
"scripts": [
"background2.js"
]
}
}
Content
• Executes on the page you see in Chrome
• Observes the page as it builds
• Intercepts the script element loading Adobe Launch
• Injects Adobe Launch monitoring hooks in response
• Receives from the extension popup the rule identifiers
• Generates the output in the console
Observe DOM Mutations
new MutationObserver(r => r.map(s => {
const t = s.addedNodes;
if(t && t.length==1){
const u = t[0];
if(u && u.nodeName=="SCRIPT" && /^https://assets.adobedtm.com/launch-/.test(u.src))
u.insertAdjacentElement("beforebegin", e);
};
})).observe(document.documentElement, {
childList: !0,
subtree: !0
});
Observe DOM Mutations
new MutationObserver(r => r.map(s => {
const t = s.addedNodes;
if(t && t.length==1){
const u = t[0];
if(u && u.nodeName=="SCRIPT" && /^https://assets.adobedtm.com/launch-/.test(u.src))
u.insertAdjacentElement("beforebegin", e);
};
})).observe(document.documentElement, {
childList: !0,
subtree: !0
});
Observe DOM Mutations
new MutationObserver(r => r.map(s => {
const t = s.addedNodes;
if(t && t.length==1){
const u = t[0];
if(u && u.nodeName=="SCRIPT" && /^https://assets.adobedtm.com/launch-/.test(u.src))
u.insertAdjacentElement("beforebegin", e);
};
})).observe(document.documentElement, {
childList: !0,
subtree: !0
});
Adobe Launch monitoring hooks
window._satellite = window._satellite || {};
window._satellite._monitors = window._satellite._monitors || [];
window._satellite._monitors.push({
ruleTriggered: q => h(q, 'rule triggered'),
ruleCompleted: q => h(q, 'rule completed'),
ruleActionFailed: q => h(q, 'rule action failed'),
ruleConditionFailed: q => h(q, 'rule condition failed')
});
Popup
<!doctype html>
<html>
<head>
<title>Duckface</title>
<link rel="stylesheet" type="text/css" href="duckface2.css" />
</head>
<body>
<form>
<input type="text" id="rule" autofocus />
<input type="button" value="Submit" id="submit" />
<input type="button" value="Reset" id="reset" />
</form>
</body>
<script type="text/javascript" src="duckface2.js"></script>
</html>
Popup
<!doctype html>
<html>
<head>
<title>Duckface</title>
<link rel="stylesheet" type="text/css" href="duckface2.css" />
</head>
<body>
<form>
<input type="text" id="rule" autofocus />
<input type="button" value="Submit" id="submit" />
<input type="button" value="Reset" id="reset" />
</form>
</body>
<script type="text/javascript" src="duckface2.js"></script>
</html>
Background
chrome.webRequest.onBeforeRequest.addListener(e => {
let f = e.url, g;
try{
if(e.requestBody && e.requestBody.raw && e.requestBody.raw[0]) g =
decodeURIComponent(String.fromCharCode.apply(null, new Uint8Array(e.requestBody.raw[0].bytes)))
if(b==e.tabId){
let D = {url : f};
if(e.method=="POST") D.postPayload = g;
C.push(D);
};
}catch(h){
console.log(h.message);
};
}, {urls : ["<all_urls>"]}, ["requestBody"]);
Background
chrome.webRequest.onBeforeRequest.addListener(e => {
let f = e.url, g;
try{
if(e.requestBody && e.requestBody.raw && e.requestBody.raw[0]) g =
decodeURIComponent(String.fromCharCode.apply(null, new Uint8Array(e.requestBody.raw[0].bytes)))
if(b==e.tabId){
let D = {url : f};
if(e.method=="POST") D.postPayload = g;
C.push(D);
};
}catch(h){
console.log(h.message);
};
}, {urls : ["<all_urls>"]}, ["requestBody"]);
Background
chrome.webRequest.onBeforeRequest.addListener(e => {
let f = e.url, g;
try{
if(e.requestBody && e.requestBody.raw && e.requestBody.raw[0]) g =
decodeURIComponent(String.fromCharCode.apply(null, new Uint8Array(e.requestBody.raw[0].bytes)))
if(b==e.tabId){
let D = {url : f};
if(e.method=="POST") D.postPayload = g;
C.push(D);
};
}catch(h){
console.log(h.message);
};
}, {urls : ["<all_urls>"]}, ["requestBody"]);
Messaging
Can
Respond
Can
Listen
Can
Initiate
Content Yes Yes Yes
Popup Yes No Yes
Background Yes Yes No
Messaging from popup to backgd
chrome.runtime.sendMessage({
somethingRandom : "Anything will do"
}, response => {
console.log(response);
});
Messaging from popup to content
chrome.tabs.query({active: true, currentWindow: true}, tabs => {
chrome.tabs.sendMessage(tabs[0].id, {
rule : rule
}, response => {
console.log(response);
});
});
Messaging from content
Same as for messages from popup to background
Received by popup and background
chrome.runtime.sendMessage({
somethingRandom : "Anything will do"
}, response => {
console.log(response);
});
Listening and responding
Only content and background scripts can listen
chrome.runtime.onMessage.addListener((message, sender,
sendResponse) => {
sendResponse({
somethingElse : "message received"
});
});
Console tricks
• console.group("this is an expanded group");
console.log(1);
console.log(2);
console.groupEnd();
• console.groupCollapsed("this is a collapsed group");
console.log(3);
console.log(4);
console.groupEnd();
Console tricks
• console.log(1);
• var a=2; console.log(`string template ${a}`);
• var b=3, c=4; console.log("%cb%cc", "color:red", "font-weight:bold");
• var d="background-
image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATC
AIAAAD9MqGbAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcw
AADsMAAA7DAcdvqGQAAAFNSURBVDhPY/hPLhjkOvfv219VUXH+3HkIF4vOSxcvT
p44MTIs3MPFtbmxsaigMDkhkZeTiwEM+Ll5YqOijx87hqKzvbVNiI+fh4NTREBQSkxc
WlxCVFAIqNrM2OTokaP37t79/v07VCnczon9/YK8fCL8AooyssryChCkKCsnKyl19swZ
iBo0wHDq5ClJUTGgwVysbHyc3ApIOuWlZfS0tKEKMQDUzh8/frx9+/bZ06cSIqIK0jIQ
nUpy8hzMLBAFmAA9hIBeF+YTAOqBaOZkYYVKYAAsYWuoqycnJQ2xk52JGSqKAbD
odHZwlJGQBOoEhpAgDx9UFANg0Tl18mRhPn6gTqB+Z3sHqCgGwKITCAS4eYAWA
mP/xfPnUCEMgF1nalKyML8AO+6ABQLsOoFAW10TqBnKwQZw6vzw4QMw0UI52A
BOnQQBuTr//wcAng5zdjL4M8cAAAAASUVORK5CYII=');background-repeat:no-
repeat"; console.log(`%c ${a} ${b} ${c}`, d);
Console tricks
• var e="expanded";
console.group(`%c ${e} group`, "font-weight:bold");
console.log(5);
console.log(6);
console.groupEnd();
• var f="collapsed";
console.groupCollapsed(`%c ${f} group`, "font-weight:italic");
console.log(5);
console.log(6);
console.groupEnd();
Console tricks
console.table([
{"d" : 1, "e" : 2, "f" : 3},
{"d" : 4, "e" : 5, "f" : 6},
{"d" : 7, "e" : 8, "f" : 9}
]);
console.table({
"a" : {"d" : 1, "e" : 2, "f" : 3},
"b" : {"d" : 4, "e" : 5, "f" : 6},
"c" : {"d" : 7, "e" : 8, "f" : 9}
});
Packing the extension
Extension demo
Extension demo
Extension demo
Quack quack!
http://www.albangerome.com
@albangerome
Thank you!
References
• All the code is available at https://github.com/alban-gerome/adobe-
analytics/blob/master/README.md
• Adobe Launch monitoring hooks info at:
• https://medium.com/adobetech/launch-library-monitoring-hooks-
c674d16deae3
• https://github.com/adobe/reactor-turbine/tree/master/src/rules

More Related Content

What's hot

Protocol-Oriented Networking
Protocol-Oriented NetworkingProtocol-Oriented Networking
Protocol-Oriented NetworkingMostafa Amer
 
The Ring programming language version 1.6 book - Part 41 of 189
The Ring programming language version 1.6 book - Part 41 of 189The Ring programming language version 1.6 book - Part 41 of 189
The Ring programming language version 1.6 book - Part 41 of 189Mahmoud Samir Fayed
 
GDG Cloud Taipei: Meetup #52 - Istio Security: API Authorization
GDG Cloud Taipei: Meetup #52 - Istio Security: API AuthorizationGDG Cloud Taipei: Meetup #52 - Istio Security: API Authorization
GDG Cloud Taipei: Meetup #52 - Istio Security: API AuthorizationKAI CHU CHUNG
 
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume LaforgeGroovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume LaforgeGuillaume Laforge
 
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTRT3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTRDavid Gómez García
 
14922 java script built (1)
14922 java script built (1)14922 java script built (1)
14922 java script built (1)dineshrana201992
 
Cross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineCross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineAndy McKay
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecturezefhemel
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETtdc-globalcode
 
maxbox starter72 multilanguage coding
maxbox starter72 multilanguage codingmaxbox starter72 multilanguage coding
maxbox starter72 multilanguage codingMax Kleiner
 
Scala for scripting
Scala for scriptingScala for scripting
Scala for scriptingday
 
SymfonyCon Berlin 2016 Jenkins Deployment Pipelines
SymfonyCon Berlin 2016 Jenkins Deployment PipelinesSymfonyCon Berlin 2016 Jenkins Deployment Pipelines
SymfonyCon Berlin 2016 Jenkins Deployment Pipelinescpsitgmbh
 
Compatibility Detector Tool of Chrome extensions
Compatibility Detector Tool of Chrome extensionsCompatibility Detector Tool of Chrome extensions
Compatibility Detector Tool of Chrome extensionsKai Cui
 
Understanding reactive programming with microsoft reactive extensions
Understanding reactive programming  with microsoft reactive extensionsUnderstanding reactive programming  with microsoft reactive extensions
Understanding reactive programming with microsoft reactive extensionsOleksandr Zhevzhyk
 
The Challenges of Container Configuration
The Challenges of Container ConfigurationThe Challenges of Container Configuration
The Challenges of Container ConfigurationGareth Rushgrove
 
The Ring programming language version 1.4.1 book - Part 18 of 31
The Ring programming language version 1.4.1 book - Part 18 of 31The Ring programming language version 1.4.1 book - Part 18 of 31
The Ring programming language version 1.4.1 book - Part 18 of 31Mahmoud Samir Fayed
 

What's hot (20)

groovy & grails - lecture 9
groovy & grails - lecture 9groovy & grails - lecture 9
groovy & grails - lecture 9
 
Protocol-Oriented Networking
Protocol-Oriented NetworkingProtocol-Oriented Networking
Protocol-Oriented Networking
 
TDD per Webapps
TDD per WebappsTDD per Webapps
TDD per Webapps
 
The Ring programming language version 1.6 book - Part 41 of 189
The Ring programming language version 1.6 book - Part 41 of 189The Ring programming language version 1.6 book - Part 41 of 189
The Ring programming language version 1.6 book - Part 41 of 189
 
GDG Cloud Taipei: Meetup #52 - Istio Security: API Authorization
GDG Cloud Taipei: Meetup #52 - Istio Security: API AuthorizationGDG Cloud Taipei: Meetup #52 - Istio Security: API Authorization
GDG Cloud Taipei: Meetup #52 - Istio Security: API Authorization
 
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume LaforgeGroovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
 
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTRT3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
 
14922 java script built (1)
14922 java script built (1)14922 java script built (1)
14922 java script built (1)
 
Cross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineCross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App Engine
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecture
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NET
 
maxbox starter72 multilanguage coding
maxbox starter72 multilanguage codingmaxbox starter72 multilanguage coding
maxbox starter72 multilanguage coding
 
Scala on Your Phone
Scala on Your PhoneScala on Your Phone
Scala on Your Phone
 
Scala for scripting
Scala for scriptingScala for scripting
Scala for scripting
 
SymfonyCon Berlin 2016 Jenkins Deployment Pipelines
SymfonyCon Berlin 2016 Jenkins Deployment PipelinesSymfonyCon Berlin 2016 Jenkins Deployment Pipelines
SymfonyCon Berlin 2016 Jenkins Deployment Pipelines
 
Compatibility Detector Tool of Chrome extensions
Compatibility Detector Tool of Chrome extensionsCompatibility Detector Tool of Chrome extensions
Compatibility Detector Tool of Chrome extensions
 
Understanding reactive programming with microsoft reactive extensions
Understanding reactive programming  with microsoft reactive extensionsUnderstanding reactive programming  with microsoft reactive extensions
Understanding reactive programming with microsoft reactive extensions
 
Test
TestTest
Test
 
The Challenges of Container Configuration
The Challenges of Container ConfigurationThe Challenges of Container Configuration
The Challenges of Container Configuration
 
The Ring programming language version 1.4.1 book - Part 18 of 31
The Ring programming language version 1.4.1 book - Part 18 of 31The Ring programming language version 1.4.1 book - Part 18 of 31
The Ring programming language version 1.4.1 book - Part 18 of 31
 

Similar to Spicy javascript: Create your first Chrome extension for web analytics QA

CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on AndroidSven Haiges
 
The Big Picture and How to Get Started
The Big Picture and How to Get StartedThe Big Picture and How to Get Started
The Big Picture and How to Get Startedguest1af57e
 
Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2Asher Martin
 
Parse cloud code
Parse cloud codeParse cloud code
Parse cloud code維佋 唐
 
Enhance Web Performance
Enhance Web PerformanceEnhance Web Performance
Enhance Web PerformanceAdam Lu
 
Paris js extensions
Paris js extensionsParis js extensions
Paris js extensionserwanl
 
How to automate all your SEO projects
How to automate all your SEO projectsHow to automate all your SEO projects
How to automate all your SEO projectsVincent Terrasi
 
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...BradNeuberg
 
Performance Metrics in a Day with Selenium
Performance Metrics in a Day with SeleniumPerformance Metrics in a Day with Selenium
Performance Metrics in a Day with SeleniumMark Watson
 
The Ring programming language version 1.10 book - Part 50 of 212
The Ring programming language version 1.10 book - Part 50 of 212The Ring programming language version 1.10 book - Part 50 of 212
The Ring programming language version 1.10 book - Part 50 of 212Mahmoud Samir Fayed
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Guillaume Laforge
 
Django - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazosDjango - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazosIgor Sobreira
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexyananelson
 
5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)Christian Rokitta
 

Similar to Spicy javascript: Create your first Chrome extension for web analytics QA (20)

CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
 
The Big Picture and How to Get Started
The Big Picture and How to Get StartedThe Big Picture and How to Get Started
The Big Picture and How to Get Started
 
Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2
 
huhu
huhuhuhu
huhu
 
Parse cloud code
Parse cloud codeParse cloud code
Parse cloud code
 
Enhance Web Performance
Enhance Web PerformanceEnhance Web Performance
Enhance Web Performance
 
Paris js extensions
Paris js extensionsParis js extensions
Paris js extensions
 
Html5 For Jjugccc2009fall
Html5 For Jjugccc2009fallHtml5 For Jjugccc2009fall
Html5 For Jjugccc2009fall
 
Nativescript angular
Nativescript angularNativescript angular
Nativescript angular
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
How to automate all your SEO projects
How to automate all your SEO projectsHow to automate all your SEO projects
How to automate all your SEO projects
 
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
 
Performance Metrics in a Day with Selenium
Performance Metrics in a Day with SeleniumPerformance Metrics in a Day with Selenium
Performance Metrics in a Day with Selenium
 
The Ring programming language version 1.10 book - Part 50 of 212
The Ring programming language version 1.10 book - Part 50 of 212The Ring programming language version 1.10 book - Part 50 of 212
The Ring programming language version 1.10 book - Part 50 of 212
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 
Django - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazosDjango - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazos
 
Sanjeev ghai 12
Sanjeev ghai 12Sanjeev ghai 12
Sanjeev ghai 12
 
Html5 Overview
Html5 OverviewHtml5 Overview
Html5 Overview
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexy
 
5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)
 

More from Alban Gérôme

Avoir de l’impact, autrement
Avoir de l’impact, autrementAvoir de l’impact, autrement
Avoir de l’impact, autrementAlban Gérôme
 
Earning more as a Digital or Web Analyst
Earning more as a Digital or Web AnalystEarning more as a Digital or Web Analyst
Earning more as a Digital or Web AnalystAlban Gérôme
 
Is it just me, or the C-suite doesn't care about data?
Is it just me, or the C-suite doesn't care about data?Is it just me, or the C-suite doesn't care about data?
Is it just me, or the C-suite doesn't care about data?Alban Gérôme
 
Cracking trading cards packs and web analytics
Cracking trading cards packs and web analyticsCracking trading cards packs and web analytics
Cracking trading cards packs and web analyticsAlban Gérôme
 
The us vs the uk web analytics job slideshare
The us vs the uk web analytics job slideshareThe us vs the uk web analytics job slideshare
The us vs the uk web analytics job slideshareAlban Gérôme
 
Implementing Web Analytics on Single Page Applications
Implementing Web Analytics on Single Page ApplicationsImplementing Web Analytics on Single Page Applications
Implementing Web Analytics on Single Page ApplicationsAlban Gérôme
 
Automating boring tasks with Powershell
Automating boring tasks with PowershellAutomating boring tasks with Powershell
Automating boring tasks with PowershellAlban Gérôme
 
Influence and Persuasion
Influence and PersuasionInfluence and Persuasion
Influence and PersuasionAlban Gérôme
 
Reshaping the Hype Cycle
Reshaping the Hype CycleReshaping the Hype Cycle
Reshaping the Hype CycleAlban Gérôme
 
Claiming credit for being data-driven
Claiming credit for being data-drivenClaiming credit for being data-driven
Claiming credit for being data-drivenAlban Gérôme
 
Acceptance, Accessible, Applicable et Auditable
Acceptance, Accessible, Applicable et AuditableAcceptance, Accessible, Applicable et Auditable
Acceptance, Accessible, Applicable et AuditableAlban Gérôme
 
Acceptance, Accessible, Actionable and Auditable
Acceptance, Accessible, Actionable and AuditableAcceptance, Accessible, Actionable and Auditable
Acceptance, Accessible, Actionable and AuditableAlban Gérôme
 
Are you still working for a data justified company?
Are you still working for a data justified company?Are you still working for a data justified company?
Are you still working for a data justified company?Alban Gérôme
 
Build your own analytics power tools
Build your own analytics power toolsBuild your own analytics power tools
Build your own analytics power toolsAlban Gérôme
 
Is data visualisation bullshit?
Is data visualisation bullshit?Is data visualisation bullshit?
Is data visualisation bullshit?Alban Gérôme
 
Acceptance, accessible, actionable and auditable
Acceptance, accessible, actionable and auditableAcceptance, accessible, actionable and auditable
Acceptance, accessible, actionable and auditableAlban Gérôme
 

More from Alban Gérôme (20)

Avoir de l’impact, autrement
Avoir de l’impact, autrementAvoir de l’impact, autrement
Avoir de l’impact, autrement
 
Earning more as a Digital or Web Analyst
Earning more as a Digital or Web AnalystEarning more as a Digital or Web Analyst
Earning more as a Digital or Web Analyst
 
Is it just me, or the C-suite doesn't care about data?
Is it just me, or the C-suite doesn't care about data?Is it just me, or the C-suite doesn't care about data?
Is it just me, or the C-suite doesn't care about data?
 
Cracking trading cards packs and web analytics
Cracking trading cards packs and web analyticsCracking trading cards packs and web analytics
Cracking trading cards packs and web analytics
 
The us vs the uk web analytics job slideshare
The us vs the uk web analytics job slideshareThe us vs the uk web analytics job slideshare
The us vs the uk web analytics job slideshare
 
Implementing Web Analytics on Single Page Applications
Implementing Web Analytics on Single Page ApplicationsImplementing Web Analytics on Single Page Applications
Implementing Web Analytics on Single Page Applications
 
Tagging differently
Tagging differentlyTagging differently
Tagging differently
 
Automating boring tasks with Powershell
Automating boring tasks with PowershellAutomating boring tasks with Powershell
Automating boring tasks with Powershell
 
Influence and Persuasion
Influence and PersuasionInfluence and Persuasion
Influence and Persuasion
 
Reshaping the Hype Cycle
Reshaping the Hype CycleReshaping the Hype Cycle
Reshaping the Hype Cycle
 
Claiming credit for being data-driven
Claiming credit for being data-drivenClaiming credit for being data-driven
Claiming credit for being data-driven
 
Acceptance, Accessible, Applicable et Auditable
Acceptance, Accessible, Applicable et AuditableAcceptance, Accessible, Applicable et Auditable
Acceptance, Accessible, Applicable et Auditable
 
Acceptance, Accessible, Actionable and Auditable
Acceptance, Accessible, Actionable and AuditableAcceptance, Accessible, Actionable and Auditable
Acceptance, Accessible, Actionable and Auditable
 
Logic or emotions
Logic or emotionsLogic or emotions
Logic or emotions
 
Hub and spoke model
Hub and spoke modelHub and spoke model
Hub and spoke model
 
Are you still working for a data justified company?
Are you still working for a data justified company?Are you still working for a data justified company?
Are you still working for a data justified company?
 
Persuasion
PersuasionPersuasion
Persuasion
 
Build your own analytics power tools
Build your own analytics power toolsBuild your own analytics power tools
Build your own analytics power tools
 
Is data visualisation bullshit?
Is data visualisation bullshit?Is data visualisation bullshit?
Is data visualisation bullshit?
 
Acceptance, accessible, actionable and auditable
Acceptance, accessible, actionable and auditableAcceptance, accessible, actionable and auditable
Acceptance, accessible, actionable and auditable
 

Recently uploaded

Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Callshivangimorya083
 
Best VIP Call Girls Noida Sector 22 Call Me: 8448380779
Best VIP Call Girls Noida Sector 22 Call Me: 8448380779Best VIP Call Girls Noida Sector 22 Call Me: 8448380779
Best VIP Call Girls Noida Sector 22 Call Me: 8448380779Delhi Call girls
 
April 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's AnalysisApril 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's Analysismanisha194592
 
Zuja dropshipping via API with DroFx.pptx
Zuja dropshipping via API with DroFx.pptxZuja dropshipping via API with DroFx.pptx
Zuja dropshipping via API with DroFx.pptxolyaivanovalion
 
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdfMarket Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdfRachmat Ramadhan H
 
Data-Analysis for Chicago Crime Data 2023
Data-Analysis for Chicago Crime Data  2023Data-Analysis for Chicago Crime Data  2023
Data-Analysis for Chicago Crime Data 2023ymrp368
 
BigBuy dropshipping via API with DroFx.pptx
BigBuy dropshipping via API with DroFx.pptxBigBuy dropshipping via API with DroFx.pptx
BigBuy dropshipping via API with DroFx.pptxolyaivanovalion
 
Accredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdfAccredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdfadriantubila
 
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...SUHANI PANDEY
 
Call me @ 9892124323 Cheap Rate Call Girls in Vashi with Real Photo 100% Secure
Call me @ 9892124323  Cheap Rate Call Girls in Vashi with Real Photo 100% SecureCall me @ 9892124323  Cheap Rate Call Girls in Vashi with Real Photo 100% Secure
Call me @ 9892124323 Cheap Rate Call Girls in Vashi with Real Photo 100% SecurePooja Nehwal
 
Smarteg dropshipping via API with DroFx.pptx
Smarteg dropshipping via API with DroFx.pptxSmarteg dropshipping via API with DroFx.pptx
Smarteg dropshipping via API with DroFx.pptxolyaivanovalion
 
Week-01-2.ppt BBB human Computer interaction
Week-01-2.ppt BBB human Computer interactionWeek-01-2.ppt BBB human Computer interaction
Week-01-2.ppt BBB human Computer interactionfulawalesam
 
Discover Why Less is More in B2B Research
Discover Why Less is More in B2B ResearchDiscover Why Less is More in B2B Research
Discover Why Less is More in B2B Researchmichael115558
 
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Callshivangimorya083
 
CebaBaby dropshipping via API with DroFX.pptx
CebaBaby dropshipping via API with DroFX.pptxCebaBaby dropshipping via API with DroFX.pptx
CebaBaby dropshipping via API with DroFX.pptxolyaivanovalion
 
Mature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptxMature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptxolyaivanovalion
 
Determinants of health, dimensions of health, positive health and spectrum of...
Determinants of health, dimensions of health, positive health and spectrum of...Determinants of health, dimensions of health, positive health and spectrum of...
Determinants of health, dimensions of health, positive health and spectrum of...shambhavirathore45
 
VidaXL dropshipping via API with DroFx.pptx
VidaXL dropshipping via API with DroFx.pptxVidaXL dropshipping via API with DroFx.pptx
VidaXL dropshipping via API with DroFx.pptxolyaivanovalion
 

Recently uploaded (20)

Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
 
Best VIP Call Girls Noida Sector 22 Call Me: 8448380779
Best VIP Call Girls Noida Sector 22 Call Me: 8448380779Best VIP Call Girls Noida Sector 22 Call Me: 8448380779
Best VIP Call Girls Noida Sector 22 Call Me: 8448380779
 
April 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's AnalysisApril 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's Analysis
 
Delhi 99530 vip 56974 Genuine Escort Service Call Girls in Kishangarh
Delhi 99530 vip 56974 Genuine Escort Service Call Girls in  KishangarhDelhi 99530 vip 56974 Genuine Escort Service Call Girls in  Kishangarh
Delhi 99530 vip 56974 Genuine Escort Service Call Girls in Kishangarh
 
Zuja dropshipping via API with DroFx.pptx
Zuja dropshipping via API with DroFx.pptxZuja dropshipping via API with DroFx.pptx
Zuja dropshipping via API with DroFx.pptx
 
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdfMarket Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
 
Data-Analysis for Chicago Crime Data 2023
Data-Analysis for Chicago Crime Data  2023Data-Analysis for Chicago Crime Data  2023
Data-Analysis for Chicago Crime Data 2023
 
BigBuy dropshipping via API with DroFx.pptx
BigBuy dropshipping via API with DroFx.pptxBigBuy dropshipping via API with DroFx.pptx
BigBuy dropshipping via API with DroFx.pptx
 
Accredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdfAccredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdf
 
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
 
Call me @ 9892124323 Cheap Rate Call Girls in Vashi with Real Photo 100% Secure
Call me @ 9892124323  Cheap Rate Call Girls in Vashi with Real Photo 100% SecureCall me @ 9892124323  Cheap Rate Call Girls in Vashi with Real Photo 100% Secure
Call me @ 9892124323 Cheap Rate Call Girls in Vashi with Real Photo 100% Secure
 
Smarteg dropshipping via API with DroFx.pptx
Smarteg dropshipping via API with DroFx.pptxSmarteg dropshipping via API with DroFx.pptx
Smarteg dropshipping via API with DroFx.pptx
 
(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7
(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7
(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7
 
Week-01-2.ppt BBB human Computer interaction
Week-01-2.ppt BBB human Computer interactionWeek-01-2.ppt BBB human Computer interaction
Week-01-2.ppt BBB human Computer interaction
 
Discover Why Less is More in B2B Research
Discover Why Less is More in B2B ResearchDiscover Why Less is More in B2B Research
Discover Why Less is More in B2B Research
 
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
 
CebaBaby dropshipping via API with DroFX.pptx
CebaBaby dropshipping via API with DroFX.pptxCebaBaby dropshipping via API with DroFX.pptx
CebaBaby dropshipping via API with DroFX.pptx
 
Mature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptxMature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptx
 
Determinants of health, dimensions of health, positive health and spectrum of...
Determinants of health, dimensions of health, positive health and spectrum of...Determinants of health, dimensions of health, positive health and spectrum of...
Determinants of health, dimensions of health, positive health and spectrum of...
 
VidaXL dropshipping via API with DroFx.pptx
VidaXL dropshipping via API with DroFx.pptxVidaXL dropshipping via API with DroFx.pptx
VidaXL dropshipping via API with DroFx.pptx
 

Spicy javascript: Create your first Chrome extension for web analytics QA

  • 1. Spicy Javascript Alban Gérôme @albangerome MeasureCamp London 11 July 2020 Your first Chrome Extension for Web Analytics QA
  • 2.
  • 3. Why a Chrome Extension? • Intercept, block, redirect, report all web requests • Inject Javascript code anywhere, any time of the page • Surface all the analytics tracking on the current web page
  • 4. Why a Chrome Extension? • Inject code on the page locally without speaking to a single web developer before the page has even finished rendering • Surface deep internal Adobe Launch rules information • Report the information using little-known Javascript console tricks
  • 5.
  • 6. The Four Elements • Manifest file • Content script • Popup script • Background script mandatory metadata runs on the current page runs in the extension popup invisible broker
  • 7.
  • 8. Manifest { "name": "Duckface", "version": "1.1", "manifest_version": 2, "description": "Adobe Launch Debugger", "browser_action": { "default_icon": "duckface-icon.png", "default_popup": "duckface2.html" }, "permissions": [ "webRequest", "<all_urls>", "activeTab" ], "content_scripts": [{ "matches": ["<all_urls>"], "js": ["content2.js"], "run_at": "document_start" }], "background": { "persistent": true, "scripts": [ "background2.js" ] } }
  • 9. Manifest { "name": "Duckface", "version": "1.1", "manifest_version": 2, "description": "Adobe Launch Debugger", "browser_action": { "default_icon": "duckface-icon.png", "default_popup": "duckface2.html" }, "permissions": [ "webRequest", "<all_urls>", "activeTab" ], "content_scripts": [{ "matches": ["<all_urls>"], "js": ["content2.js"], "run_at": "document_start" }], "background": { "persistent": true, "scripts": [ "background2.js" ] } }
  • 10. Manifest { "name": "Duckface", "version": "1.1", "manifest_version": 2, "description": "Adobe Launch Debugger", "browser_action": { "default_icon": "duckface-icon.png", "default_popup": "duckface2.html" }, "permissions": [ "webRequest", "<all_urls>", "activeTab" ], "content_scripts": [{ "matches": ["<all_urls>"], "js": ["content2.js"], "run_at": "document_start" }], "background": { "persistent": true, "scripts": [ "background2.js" ] } }
  • 11. Manifest { "name": "Duckface", "version": "1.1", "manifest_version": 2, "description": "Adobe Launch Debugger", "browser_action": { "default_icon": "duckface-icon.png", "default_popup": "duckface2.html" }, "permissions": [ "webRequest", "<all_urls>", "activeTab" ], "content_scripts": [{ "matches": ["<all_urls>"], "js": ["content2.js"], "run_at": "document_start" }], "background": { "persistent": true, "scripts": [ "background2.js" ] } }
  • 12. Manifest { "name": "Duckface", "version": "1.1", "manifest_version": 2, "description": "Adobe Launch Debugger", "browser_action": { "default_icon": "duckface-icon.png", "default_popup": "duckface2.html" }, "permissions": [ "webRequest", "<all_urls>", "activeTab" ], "content_scripts": [{ "matches": ["<all_urls>"], "js": ["content2.js"], "run_at": "document_start" }], "background": { "persistent": true, "scripts": [ "background2.js" ] } }
  • 13.
  • 14. Content • Executes on the page you see in Chrome • Observes the page as it builds • Intercepts the script element loading Adobe Launch • Injects Adobe Launch monitoring hooks in response • Receives from the extension popup the rule identifiers • Generates the output in the console
  • 15. Observe DOM Mutations new MutationObserver(r => r.map(s => { const t = s.addedNodes; if(t && t.length==1){ const u = t[0]; if(u && u.nodeName=="SCRIPT" && /^https://assets.adobedtm.com/launch-/.test(u.src)) u.insertAdjacentElement("beforebegin", e); }; })).observe(document.documentElement, { childList: !0, subtree: !0 });
  • 16. Observe DOM Mutations new MutationObserver(r => r.map(s => { const t = s.addedNodes; if(t && t.length==1){ const u = t[0]; if(u && u.nodeName=="SCRIPT" && /^https://assets.adobedtm.com/launch-/.test(u.src)) u.insertAdjacentElement("beforebegin", e); }; })).observe(document.documentElement, { childList: !0, subtree: !0 });
  • 17. Observe DOM Mutations new MutationObserver(r => r.map(s => { const t = s.addedNodes; if(t && t.length==1){ const u = t[0]; if(u && u.nodeName=="SCRIPT" && /^https://assets.adobedtm.com/launch-/.test(u.src)) u.insertAdjacentElement("beforebegin", e); }; })).observe(document.documentElement, { childList: !0, subtree: !0 });
  • 18.
  • 19. Adobe Launch monitoring hooks window._satellite = window._satellite || {}; window._satellite._monitors = window._satellite._monitors || []; window._satellite._monitors.push({ ruleTriggered: q => h(q, 'rule triggered'), ruleCompleted: q => h(q, 'rule completed'), ruleActionFailed: q => h(q, 'rule action failed'), ruleConditionFailed: q => h(q, 'rule condition failed') });
  • 20.
  • 21. Popup <!doctype html> <html> <head> <title>Duckface</title> <link rel="stylesheet" type="text/css" href="duckface2.css" /> </head> <body> <form> <input type="text" id="rule" autofocus /> <input type="button" value="Submit" id="submit" /> <input type="button" value="Reset" id="reset" /> </form> </body> <script type="text/javascript" src="duckface2.js"></script> </html>
  • 22. Popup <!doctype html> <html> <head> <title>Duckface</title> <link rel="stylesheet" type="text/css" href="duckface2.css" /> </head> <body> <form> <input type="text" id="rule" autofocus /> <input type="button" value="Submit" id="submit" /> <input type="button" value="Reset" id="reset" /> </form> </body> <script type="text/javascript" src="duckface2.js"></script> </html>
  • 23.
  • 24. Background chrome.webRequest.onBeforeRequest.addListener(e => { let f = e.url, g; try{ if(e.requestBody && e.requestBody.raw && e.requestBody.raw[0]) g = decodeURIComponent(String.fromCharCode.apply(null, new Uint8Array(e.requestBody.raw[0].bytes))) if(b==e.tabId){ let D = {url : f}; if(e.method=="POST") D.postPayload = g; C.push(D); }; }catch(h){ console.log(h.message); }; }, {urls : ["<all_urls>"]}, ["requestBody"]);
  • 25. Background chrome.webRequest.onBeforeRequest.addListener(e => { let f = e.url, g; try{ if(e.requestBody && e.requestBody.raw && e.requestBody.raw[0]) g = decodeURIComponent(String.fromCharCode.apply(null, new Uint8Array(e.requestBody.raw[0].bytes))) if(b==e.tabId){ let D = {url : f}; if(e.method=="POST") D.postPayload = g; C.push(D); }; }catch(h){ console.log(h.message); }; }, {urls : ["<all_urls>"]}, ["requestBody"]);
  • 26. Background chrome.webRequest.onBeforeRequest.addListener(e => { let f = e.url, g; try{ if(e.requestBody && e.requestBody.raw && e.requestBody.raw[0]) g = decodeURIComponent(String.fromCharCode.apply(null, new Uint8Array(e.requestBody.raw[0].bytes))) if(b==e.tabId){ let D = {url : f}; if(e.method=="POST") D.postPayload = g; C.push(D); }; }catch(h){ console.log(h.message); }; }, {urls : ["<all_urls>"]}, ["requestBody"]);
  • 27.
  • 28. Messaging Can Respond Can Listen Can Initiate Content Yes Yes Yes Popup Yes No Yes Background Yes Yes No
  • 29. Messaging from popup to backgd chrome.runtime.sendMessage({ somethingRandom : "Anything will do" }, response => { console.log(response); });
  • 30. Messaging from popup to content chrome.tabs.query({active: true, currentWindow: true}, tabs => { chrome.tabs.sendMessage(tabs[0].id, { rule : rule }, response => { console.log(response); }); });
  • 31. Messaging from content Same as for messages from popup to background Received by popup and background chrome.runtime.sendMessage({ somethingRandom : "Anything will do" }, response => { console.log(response); });
  • 32. Listening and responding Only content and background scripts can listen chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { sendResponse({ somethingElse : "message received" }); });
  • 33.
  • 34. Console tricks • console.group("this is an expanded group"); console.log(1); console.log(2); console.groupEnd(); • console.groupCollapsed("this is a collapsed group"); console.log(3); console.log(4); console.groupEnd();
  • 35. Console tricks • console.log(1); • var a=2; console.log(`string template ${a}`); • var b=3, c=4; console.log("%cb%cc", "color:red", "font-weight:bold"); • var d="background- image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATC AIAAAD9MqGbAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcw AADsMAAA7DAcdvqGQAAAFNSURBVDhPY/hPLhjkOvfv219VUXH+3HkIF4vOSxcvT p44MTIs3MPFtbmxsaigMDkhkZeTiwEM+Ll5YqOijx87hqKzvbVNiI+fh4NTREBQSkxc WlxCVFAIqNrM2OTokaP37t79/v07VCnczon9/YK8fCL8AooyssryChCkKCsnKyl19swZ iBo0wHDq5ClJUTGgwVysbHyc3ApIOuWlZfS0tKEKMQDUzh8/frx9+/bZ06cSIqIK0jIQ nUpy8hzMLBAFmAA9hIBeF+YTAOqBaOZkYYVKYAAsYWuoqycnJQ2xk52JGSqKAbD odHZwlJGQBOoEhpAgDx9UFANg0Tl18mRhPn6gTqB+Z3sHqCgGwKITCAS4eYAWA mP/xfPnUCEMgF1nalKyML8AO+6ABQLsOoFAW10TqBnKwQZw6vzw4QMw0UI52A BOnQQBuTr//wcAng5zdjL4M8cAAAAASUVORK5CYII=');background-repeat:no- repeat"; console.log(`%c ${a} ${b} ${c}`, d);
  • 36. Console tricks • var e="expanded"; console.group(`%c ${e} group`, "font-weight:bold"); console.log(5); console.log(6); console.groupEnd(); • var f="collapsed"; console.groupCollapsed(`%c ${f} group`, "font-weight:italic"); console.log(5); console.log(6); console.groupEnd();
  • 37. Console tricks console.table([ {"d" : 1, "e" : 2, "f" : 3}, {"d" : 4, "e" : 5, "f" : 6}, {"d" : 7, "e" : 8, "f" : 9} ]); console.table({ "a" : {"d" : 1, "e" : 2, "f" : 3}, "b" : {"d" : 4, "e" : 5, "f" : 6}, "c" : {"d" : 7, "e" : 8, "f" : 9} });
  • 44. References • All the code is available at https://github.com/alban-gerome/adobe- analytics/blob/master/README.md • Adobe Launch monitoring hooks info at: • https://medium.com/adobetech/launch-library-monitoring-hooks- c674d16deae3 • https://github.com/adobe/reactor-turbine/tree/master/src/rules