Desktop Solutions
Direct tracking code injection to extension
9min
before we get started, it's important to understand what a tracking code is and why it is used when a user installs your extension, we need a way to identify the user to affiliate when they activate cash back through your extension, in order to attribute them properly when the sale completes its lifecycle this is done at wildfire by attaching a tc query parameter at the end of your affiliate url once the sale completes it's lifecycle, you can retrieve the value within the tc parameter by going in to the admin tool, and posting the data to your callback url example of a vanity url with a tc parameter \<https //wild link/lovepop/aiul ai?tc=ee5f1a61 a2f1 4cde be78 293fa339e592> example of an offline vanity url with a tc parameter \<https //wild link/e?d=0\&c=0\&tc=2d4109a6 c5f6 4028 a206 c26b1379ea82\&url=https //example com> many extensions use different models, whether it's an oauth flow, or logging in directly through the extension they all serve the purpose of having the user identify themselves, and saving that identifier in the extension's storage this way is different because it doesn't require us making an http request within the extension after authenticating, and not storing any secrets in the extension when not needed final things to note before we get started the identifiers in the example urls are uuids, your platform may have different ways of identifying a user, the premise is the same this method is only known to work in chrome and firefox safari does not allow the onmessageexternalmethod to be exposed for extensions during this tutorial we will assume you have some knowledge of how chrome extensions work please check the documentation https //developer chrome com/docs/extensions/mv2/ for basic information on getting a chrome extension setup and how they work we will be using the v2 manifest version in the examples the example code will contain a directory depicting an example web page that is ran locally on your computer you can run a web server from vscode using the live server https //marketplace visualstudio com/items?itemname=ritwickdey liveserver extension you can access the example code at the bottom of this document in the example extension we depict that the user is logged in based off whether or not the tracking code is stored within the extension this behavior is common amongst our cash back extensions, primarily because we don't want the user activating cash back if we have no way of identifying who the user is with that out of the way let's get started take a look at the directory structure of the example code the extension directory contains the extension code, the website directory contains the code for your website your structure may look different update your manifest json with the following specify your web page as an externally connectable web page this enables the extension to communicate with tabs that have urls that match the matches property add a key in your manifest json to create a permanent extension id this id will be used to communicate from your web page to your extension for information on how to generate your own key see here https //stackoverflow\ com/a/46739698 the extension id in our example is aokkbecooohkgppimfffkongjlpihbol manifest json { "manifest version" 2, "name" "example", "description" "example", "version" "1 0 0", "key" "miibijanbgkqhkig9w0baqefaaocaq8amiibcgkcaqea5yyhythdwmwwn3pvwrikjdycayxscunwpqqxatgbz8+835xffblfjdjjzqyo2rautzcuhp3cxunzj7ljm2wivfsncktau/u23mfgf92gk0xznj+de0fhbuzdwaa649jqzrb5gm2v49sgrojayy6ktwmvmj13a1+kovrm3z1u33yn6nuyhlxtbt6bjhbxxmoe+ldt/owe2tl5eauvc37muypgjg9/dlgww2ucteyfmq9gl/hymqtofwtl8ofnjr0cyrpojnl+9bnfy2yexbz98kuim8g6ibm/znwzfyybf8z+irpqmvxa7iicu0qn2pctav4yj6avmgcnmy0hapn7iqidaqab", "background" { "scripts" \["background js"] }, "content scripts" \[ { "js" \["content js"], "matches" \["\<all urls>"] } ], "browser action" { "default popup" "popup html", "default icon" { "16" "images/toolbar icon 16 png", "19" "images/toolbar icon 19 png", "32" "images/toolbar icon 32 png", "38" "images/toolbar icon 38 png" } }, "externally connectable" { "matches" \[ "https // yoursite com/ ", "\<http //127 0 0 1 5500/ >" ] } } the "https // yoursite com/ " value is there as a placeholder for you to enter you own url the \[\<http //127 0 0 1 5500/ >]\(\<http //127 0 0 1 5500/ >) is there for testing we will be running our webpage through live server https //marketplace visualstudio com/items?itemname=ritwickdey liveserver via vscode, you may be using something like web pack dev server or another local server if you are using something else, make sure to update the port number in your manifest json we can now move to the extension code this is our background js file background js let trackingcode = null; chrome runtime onmessageexternal addlistener( (message, sender, sendresponse) => { switch (message status) { // the initial ping will let the web page know that we can communicate with the extension case "ping" console log("received ping from", sender origin); sendresponse(true); break; case "set tracking code" const { code } = message payload; console log("received ", code); trackingcode = code; sendresponse(true); break; } } ); // listener added to communicate with the popup/content script chrome runtime onmessage addlistener((message, sender, sendresponse) => { switch (message status) { case "is logged in" sendresponse(!!trackingcode); break; } }); the onmessageexternal listener dispatches an event when an outside entity communicates with the extension we have the ping message to send back true to let the webpage know that we are able to communicate the set tracking code message is there for us to save the tracking code within the extension in our example we are saving it in memory, but you will more than likely saving it to browser storage the onmessage listener dispatches an event when the content script or the popup script sends a message to background script the is logged in message is there to validate whether or not the extension has a tracking code in memory this is our popup js file popup js chrome runtime sendmessage({ status "is logged in" }, (isloggedin) => { const button = document queryselector("button"); button textcontent = isloggedin ? "logged in" "not logged in"; button style backgroundcolor = isloggedin ? "green" "red"; }); when the popup is rendered, we check and see if the tracking code has been stored in the background the idea behind this behavior is that we don't want our user using our extension without first identifying themselves through our webpage let's move to our webpage and fire it up using live server https //marketplace visualstudio com/items?itemname=ritwickdey liveserver this file is website/index html index html login send code submit if your button and input fields are greyed out, then you did not set your key properly you can change the extensionid on line 8 of the website/main js file here is said file / your extension id to specify your extension when sending the message for information on how to generate your own extension id see here \<https //stackoverflow\ com/a/46739698> once you have your key generated, you can add the key to your manifest json under the "key" property if you have not set the id properly, or made this webpage externally connectable you will get the following error `unchecked runtime lasterror could not establish connection receiving end does not exist ` / const extensionid = "aokkbecooohkgppimfffkongjlpihbol"; / only here to make sure you are on the correct browser / const ischromeapiaccessible = typeof window\ chrome !== "undefined" && typeof window\ chrome runtime !== "undefined" && typeof window\ chrome runtime sendmessage !== "undefined"; const submitbutton = document queryselector("button"); const inputelement = document queryselector("input"); / wrapped in an iffe to stop execution when needed / (() => { try { if (!ischromeapiaccessible) { return console log("stopping execution, chrome api is not accessible "); } window\ chrome runtime sendmessage( extensionid, { status "ping" }, (isconnected) => { if (!isconnected) { return console log( "stopping execution, failed to connect to the extension" ); } console log("successfully pinged extension, ready to accept code"); submitbutton disabled = false; inputelement disabled = false; submitbutton onclick = () => { const code = inputelement value; window\ chrome runtime sendmessage( extensionid, { status "set tracking code", payload { code } }, (wassuccessful) => { if (!wassuccessful) { return console log("failed to send code"); } console log("successfully sent code"); } ); }; } ); } catch (err) { console error("failed to communicate with the extension", err); } })(); this file does the following on initial load it checks to see if the chrome api is accessible if your chrome api is not accessible you may be on the wrong browser selects the input and button elements for use later fires off an immediately invoked function we wrap in an iffe here to be able to stop the execution of the rest of the code we send a ping to the extension to make sure we can communicate with it first if we can't then the input and button remain disabled if we are able to communicate with the extension, then we enable the input and button then we add an event listener on the button for you to send the tracking code to the extension side you can incorporate this logic into your own web pages when to send the message is up to you, but it is probably best to do so when the user first logs in through your web page or first lands on your page if returning in a logged in state this saves us the hassle of creating an oauth login flow and saves you the danger of exposing secrets in your extension code example project zip https //www wildfire corp com/hubfs/uuid%20injection%20example zip