Intergrate google adwords tracking with salesforce - javascript

im trying to integrate google adwords tracking with salesforce based on this
https://www.e-nor.com/blog/google-analytics/integrate-salesforce-and-google-analytics
i have created hidden fields in salesforce and add the code to the form and the js script to capture the values but i having problem i dont get any data coming in
test.php?utm_source=google&utm_medium=CPC&utm_campaign=test&utm_term=test
<input type="hidden" name="medium" id="medium" value="" />
<input type="hidden" name="source" id="source" value="" />
<input type="hidden" name="campaign" id="campaign" value="" />
<input type="hidden" name="term" id="term" value="" />
<script type="text/javascript">
var z = _uGC(document.cookie, '__utmz=', ';');
var source = _uGC(z, 'utmcsr=', '|');
var medium = _uGC(z, 'utmcmd=', '|');
var term = _uGC(z, 'utmctr=', '|');
var content = _uGC(z, 'utmcct=', '|');
var campaign = _uGC(z, 'utmccn=', '|');
var gclid = _uGC(z, 'utmgclid=', '|');
if (gclid !="-") {
source = 'google';
medium = 'cpc';
}
var csegment = _uGC(document.cookie, '__utmv=', ';');
if (csegment != '-') {
var csegmentex = /[1-9]*?\.(.*)/;
csegment = csegment.match(csegmentex);
csegment = csegment[1];
} else {
csegment = '';
}
function _uGC(l,n,s)
{
if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
var i,i2,i3,c="-";
i=l.indexOf(n);
i3=n.indexOf("=")+1;
if (i > -1) {
i2=l.indexOf(s,i); if (i2 < 0){ i2=l.length; }
c=l.substring((i+i3),i2);
}
return c;
}
document.getElementById("medium").value =medium; /* Campaign_Medium */
document.getElementById("source").value =source; /* Campaign_Source */
document.getElementById("campaign").value =campaign; /* Campaign_CampaignName */
document.getElementById("term").value =term; /* Campaign_Term */
</script>

Okay, if I understand correctly you are trying to do a Web-to-Lead process and you want to capture the campaign information.
As I see it your current approach has two major flaws: The current version of Google Analytics (Universal Analytics, which uses the analytics.js tracking library) does not evaluate campaign information on the client side and does not store in in the cookie (UA uses a single cookie that only hold a client id).
But even if it did it would probably not help you with your Adwords data. Chances are pretty good that you have autotagging enabled, and in that you would not have campaign information for Adwords even with the old Google Analytics code. Adwords uses a Google Click id, or gclid, that is resolved into readable campaign parameters only after GA has retrieved to information from a linked Adwords account; on the client side you can only read the gclid parameter which does not help you.
So I suggest a different approach that should work well as long as you do not need the data in realtime, and as long as you a prepared to do some serverside programming instead of Javascript (which simply cannot do what you want). It goes basically like this:
Instead of sending campaign data along with your Web-To-Lead form you send just a unique id for the lead, and store in a custom field in Salesforce. You send the same id to Google Analytics as custom dimension that you have created before in a hit level scope by attaching a click event to the submit button (or submit event to the form), send a Google Analytics event and include the id as custom dimension.
Google Analytics needs a bit of processing time, so you wait until the next day. By then GA will have resolved the Adwords click ids into readable source/medium/campaign parameters (plus term and content if you need that, and it will have imported Adwords-related metrics).
You then query the Google Analytics Reporting API to retrieve the submit events from GA with your custom id and the campaign information. Then you send the campaign data via the Salesforce API to SF and store it in custom fields in your lead entities. Run the script once periodically and it will update all your leads with the data from GA.
The biggest drawback is possibly that API access is not available for all Salesforce editions. According to this knowledgebase article API access is enabled in Enterprise/Unlimited/Performance and Developer editions and can be enabled for a fee in the professional edition.
It has turned out to be impossible for me to cram instructions for the whole process into an stackoverflow post, so I wrote a tutorial that covers all steps. This requires some serverside programming - the tutorial uses python, and it should include enough information to get the program running even if you do not know Python. It's broken up into several parts, so you can skip the bits you are already familiar with.
Part 1 - Restating the Problem
Part 2 - The Programming Environment used in the tutorial
Part 3 - APIs and Authentication
Part 4 - Setting up Salesforce and Google Analytics
Part 5 - Libraries and example code
It might be that the links will be removed for being to self-promotional (they lead to my blog), but even so this post should give you an idea how to approach the problem.

I am not sure if you are using the correct codes and the correct sequence to do that, check my post here and use the same codes and instructions I am using to track Source, Medium, Campaign and Term, I fully tested it and it is working fine.
Your approach is correct, but I am not sure if you are trying to read the cookies before they are even created, if this is your landing page test.php?utm_source=google&utm_medium=CPC&utm_campaign=test&utm_term=test and it is the same page where you are trying to fill the hidden fields make sure the Javascript code/function that generates the cookies (function _uGC) get executed before the code that tries to fill in the fields

Related

How to submit a form and execute javascript simultaneously

As a follow-up to my last question, I have run into another problem. I am making a project on google homepage replica. The aim is to show search results the same as google and store the search history on a database. To show results, I have used this javascript:-
const q = document.getElementById('form_search');
const google = 'https://www.google.com/search?q=';
const site = '';
function google_search(event) {
event.preventDefault();
const url = google + site + '+' + q.value;
const win = window.open(url, '_self');
win.focus();
}
document.getElementById("s-btn").addEventListener("click", google_search)
To create my form, I have used the following HTML code:-
<form method="POST" name="form_search" action="form.php">
<input type="text" id="form_search" name="form_search" placeholder="Search Google or type URL">
The terms from the search bar are to be sent to a PHP file with the post method. I have 2 buttons. Let's name them button1 and button2. The javascript uses the id of button1 while button2 has no javascript and is simply a submit button.
The problem is that when I search using button1, the search results show up but no data is added to my database. But when I search using button2, no results show up( obviously because there is no js for it) but the search term is added to my database. If I reverse the id in javascript, the outcome is also reversed. I need help with making sure that when I search with button1, it shows results and also saves the data in the database. If you need additional code, I will provide it. Please keep your answers limited to javascript, PHP, or HTML solutions. I have no experience with Ajax and JQuery. Any help is appreciated.
Tony since there is limited code available so go with what you had stated in your question.
It is a design pattern issue not so much as so the event issue.
Copy pasting from Wikipedia "software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design. It is not a finished design that can be transformed directly into source or machine code. Rather, it is a description or template for how to solve a problem that can be used in many different situations. Design patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system."
So here is how things play out at present;
forms gets submitted to specific URL i.e. based on action attribute
Requested page gets Query sting in php and lets you play around with it
then from there on .....
3. either you get results from database and return response
4. or you put search request into database and return success response
Problem statement
if its 3 then search request is not added to database if its 4 then results in response to search request are not returned.
Solution
you need to combine both 3 and 4 in to one processing block and will always run regardless of the search query is.
So our design pattern could use mysql transaction so whole bunch of queries would run a single operation example
$db->beginTransaction(); // we tell tell mysql we will multiple queries as single operation
$db->query('insert query');
$results= $db->query('search query');
$db->commit(); // if we have reached to this end it means all went fine no error etc so we commit which will make database record insert query into database. If there were errors then mysql wont record data.
if($results) {echo $results;} else {echo 'opps no result found';}
slightly more safe version
try {
$db->beginTransaction(); // we tell tell mysql we will multiple queries as single operation
$db->query('insert query');
$results= $db->query('search query');
$db->commit(); // if we have reached to this end it means all went fine no error etc so we commit which will make database record insert query into database. If there were errors then mysql wont record data.
if($results) {echo $results;} else {echo 'opps no result found';}
} catch (\Throwable $e) {
// An exception has been thrown must rollback the transaction
$db->rollback();
echo 'oho server could not process request';
}
We have effectively combined two query operation into one always recording into database and always searching in database.

Google Apps Script Bad Value

I'm getting a "bad value on line 4"... I don't know why. I'm trying to make a Google sheet that automatically opens to an assigned tab based on gmail address for a large team. Please help!
function onOpen() {
var email = Session.getActiveUser().getEmail();
var username = email.slice(0,-9);
var ss = SpreadsheetApp.openById(username);
SpreadsheetApp.setActiveSpreadsheet(ss);
}
I suspect here your issue is a misunderstanding of the function '.openById()'.
This function is designed so that you identify and open the spreadsheet using a spreadsheet ID (The alphanumeric part of the URL when opening a sheet, such as "abc1234567"). From context and your use of the variable 'username', I think that instead you're somehow trying to open it based on an email ID (Such as user#domain.com).
Incidentally, you won't be able to open the sheet in an assigned tab using Scripts. That's not what it does, and it's unable to manipulate a users browser. Perhaps an extension for Chrome would be closer to what you're looking for.

How to Call Google Apps Script from Web Page

Have searched high and low for this. I have a web page of basic HTML/CSS/JS. I want users to be able to visit the page and upon opening page, a call is made to a google script I made which takes information from a spreadsheet and displays some of it on the page. I am hoping I don't have to do any fancy set up like in Google's tutorials because none of them were helpful to me.
My Webpage ----> Google Script ----> Google Spreadsheet
My Webpage <---- Google Script <---- Google Spreadsheet
Users should be able to select an item shown on the webpage (item populated from spreadsheet) and click a button which will allow users to enter a new page with a URL derived from the selected item.
This is essentially a chat room program where the chat rooms are stored on a spreadsheet. I want users to be able to create a new chat room as well which should update the google spreadsheet.
Look into using the GET parameters. https://stackoverflow.com/a/14736926/2048063.
Here's a previous question on the topic.
You can access the parameters passed by GET in your doGet(e) function using e.parameter. If you call http://script.google......./exec?method=doSomething, then
function doGet(e) {
Logger.log(e.parameter.method);
}
doSomething will be written to the log, in this case.
Returning data from the script can be done using the ContentService, which allows you to serve JSON (I recommend). JSON is easiest (in my opinion) to make on the GAS end, as well as use on the client end.
The initial "populate list" call would look something like this. I will write it in jQuery because I feel that is very clean.
var SCRIPT_URL = "http://script.google.com/[....PUT YOUR SCRIPT URL HERE....]/exec";
$(document).ready(function() {
$.getJSON(SCRIPT_URL+"?callback=?",
{method:"populate_list"},
function (data) {
alert(JSON.stringify(data));
});
});
And the corresponding GAS that produces this.
function doGet(e) {
if (e.parameter.method=="populate_list") {
var v = {cat:true,dog:false,meow:[1,2,3,4,5,6,4]}; //could be any value that you want to return
return ContentService.createTextOutput(e.parameter.callback + "(" + JSON.stringify(v) + ")")
.setMimeType(ContentService.MimeType.JAVASCRIPT);
}
}
This method is called JSONP, and it is supported by jQuery. jQuery recognizes it when you put the ?callback=? after your URL. It wraps your output in a callback function, which allows that function to be run on your site with the data as an argument. In this case, the callback function is the one defined in the line that reads function (data) {.

Get Twitter Feed as JSON without authentication

I wrote a small JavaScript a couple of years ago that grabbed a users (mine) most recent tweet and then parsed it out for display including links, date etc.
It used this json call to retrieve the tweets and it no longer works.
http://twitter.com/statuses/user_timeline/radfan.json
It now returns the error:
{"errors":[{"message":"Sorry, that page does not exist","code":34}]}
I have looked at using the api version (code below) but this requires authentication which I would rather avoid having to do as it is just to display my latest tweet on my website which is public anyway on my profile page:
http://api.twitter.com/1/statuses/radfan.json
I haven't kept up with Twitter's API changes as I no longer really work with it, is there a way round this problem or is it no longer possible?
Previously the Search API was the only Twitter API that didn't require some form of OAuth. Now it does require auth.
Twitter's Search API is acquired from a third party acquisition - they rarely support it and are seemingly unenthused that it even exists. On top of that, there are many limitations to the payload, including but not limited to a severely reduced set of key:value pairs in the JSON or XML file you get back.
When I heard this, I was shocked. I spent a LONG time figuring out how to use the least amount of code to do a simple GET request (like displaying a timeline).
I decided to go the OAuth route to be able to ensure a relevant payload. You need a server-side language to do this. JavaScript is visible to end users, and thus it's a bad idea to include the necessary keys and secrets in a .js file.
I didn't want to use a big library so the answer for me was PHP and help from #Rivers' answer here. The answer below it by #lackovic10 describes how to include queries in your authentication.
I hope this helps others save time thinking about how to go about using Twitter's API with the new OAuth requirement.
You can access and scrape Twitter via advanced search without being logged in:
https://twitter.com/search-advanced
GET request
When performing a basic search request you get:
https://twitter.com/search?q=Babylon%205&src=typd
q (our query encoded)
src (assumed to be the source of the query, i.e. typed)
by default, Twitter returns top 25 results, but if you click on
all you can get the realtime tweets:
https://twitter.com/search?f=realtime&q=Babylon%205&src=typd
JSON contents
More Tweets are loaded on the page via AJAX:
https://twitter.com/i/search/timeline?f=realtime&q=Babylon%205&src=typd&include_available_features=1&include_entities=1&last_note_ts=85&max_position=TWEET-553069642609344512-553159310448918528-BD1UO2FFu9QAAAAAAAAETAAAAAcAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Use max_position to request the next tweets
The following json array returns all you need to scrape the contents:
https://twitter.com/i/search/timeline?f=realtime&q=Babylon%205&src=typd
has_more_items (bool)
items_html (html)
max_position (key)
refresh_cursor (key)
DOM elements
Here comes a list of DOM elements you can use to extract
The authors twitter handle
div.original-tweet[data-tweet-id]
The name of the author
div.original-tweet[data-name]
The user ID of the author
div.original-tweet[data-user-id]
Timestamp of the post
span._timestamp[data-time]
Timestamp of the post in ms
span._timestamp[data-time-ms]
Text of Tweet
p.tweet-text
Number of Retweets
span.ProfileTweet-action–retweet > span.ProfileTweet-actionCount[data-tweet-stat-count]
Number of Favo
span.ProfileTweet-action–favorite > span.ProfileTweet-actionCount[data-tweet-stat-count]
Resources
https://code.recuweb.com/2015/scraping-tweets-directly-from-twitter-without-authentication/
If you're still looking for unauthenticated tweets in JSON, this should work:
https://github.com/cosmocatalano/tweet-2-json
As you can see in the documentation, using the REST API you'll need OAuth Tokens in order to do this. Luckily, we can use the Search (which doesn't use OAuth) and use the from:[USERNAME] operator
Example:
http://search.twitter.com/search.json?q=from:marcofolio
Will give you a JSON object with tweets from that user, where
object.results[0]
will give you the last tweet.
Here is a quick hack (really a hack, should be used with caution as its not future proof) which uses http://anyorigin.com to scrape twitter site for the latest tweets.
http://codepen.io/JonOlick/pen/XJaXBd
It works by using anyorigin (you have to pay to use it) to grab the HTML. It then parses the HTML using jquery to extract out the relevant tweets.
Tweets on the mobile site use a div with the class .tweet-text, so this is pretty painless.
The relevant code looks like this:
$.getJSON('http://anyorigin.com/get?url=mobile.twitter.com/JonOlick&callback=?', function(data){
// Remap ... utf8 encoding to ascii.
var bar = data.contents;
bar = bar.replace(/…/g, '...');
var el = $( '<div></div>' );
el.html(bar);
// Change all links to point back at twitter
$('.twitter-atreply', el).each(function(i){
$(this).attr('href', "https://twitter.com" + $(this).attr('href'))
});
// For all tweets
$('.tweet-text', el).each(function(i){
// We only care about the first 4 tweets
if(i < 4) {
var foo = $(this).html();
$('#test').html($('#test').html() + "<div class=ProfileTweet><div class=ProfileTweet-contents>" + foo + "</div></div><br>");
}
});
});
You can use a Twitter API wrapper, such as TweetJS.com which offers a limited set of the Twitter API's functionality, but does not require authentication. It's called like this;
TweetJs.ListTweetsOnUserTimeline("PetrucciMusic",
function (data) {
console.log(data);
});
You can use the twitter api v1 to take the tweets without using OAuth. For example: this link turns #jack's last 100 tweets.
The timeline documentation is here.
The method "GET statuses/user_timeline" need a user Authentification like you can see on the official documentation :
You can use the search method "GET search" wich not require authentification.
You have a code for starting here : http://jsfiddle.net/73L4c/6/
function searchTwitter(query) {
$.ajax({
url: 'http://search.twitter.com/search.json?' + jQuery.param(query),
dataType: 'jsonp',
success: function(data) {
var tweets = $('#tweets');
tweets.html('');
for (res in data['results']) {
tweets.append('<div>' + data['results'][res]['from_user'] + ' wrote: <p>' + data['results'][res]['text'] + '</p></div><br />');
}
}
});
}
$(document).ready(function() {
$('#submit').click(function() {
var params = {
q: $('#query').val(),
rpp: 5
};
// alert(jQuery.param(params));
searchTwitter(params);
});
})

Best way to obfuscate an e-mail address on a website?

I've spent the past few days working on updating my personal website. The URL of my personal website is (my first name).(my last name).com, as my last name is rather unusual, and I was lucky enough to pick up the domain name. My e-mail address is (my first name)#(my last name).com. So really, when it comes down to guessing it, it's not very hard.
Anyways, I want to integrate a mailto: link into my website, so people can contact me. And, despite my e-mail address not being very hard to guess, I'd rather not have it harvested by spam bots that just crawl websites for e-mail address patterns and add them to their database.
What is the best way for me to obfuscate my e-mail address, preferably in link form? The methods I know of are:
e-mail me
It works, but it also means that as soon as my website hits Google, I'll be wading through spam as spam bots easily pick out my e-mail address.
<img src="images/e-mail.png" />
This is less desirable, because not only will visitors be unable to click on it to send me an e-mail, but smarter spam bots will probably be able to detect the characters that the image contains.
I know that there is probably no perfect solution, but I was just wondering what everyone thought was best. I'm definitely willing to use JavaScript if necessary, as my website already makes use of tons of it.
I encode the characters as HTML entities (something like this). It doesn't require JS to be enabled and seems to have stopped most of the spam. I suppose a smart bot might still harvest it, but I haven't had any problems.
Personally, I've given up on hiding my email address. I find it easier to look into better spam-filtering solutions than worry about obfuscating. You could spend days trying to find the best way to obfuscate your address, and then all it takes is one person to sell your address to a spammer and all that work was useless.
The current accepted solution is to create a contact form that allows users to email you. If you receive a lot of spam from that (I don't on my site), then you can add a captcha for good measure, and you'll be far from the "low hanging fruit" at that point.
The fact of the matter is that if you are providing a link that a user can click on to pop open their email client with your address in the To: field, then the computer is able to decipher the email address from the page and so can a spam bot.
You mentioned this is for your personal website. On my personal site (for example, bobsomers.com) I just have a paragraph that says this:
The best way to get in contact with me
before the new site is up is to send
me an email. My email address is my
first name at this website. If you
can't figure it out from that hint,
well, you might find email more of a
challenge than figuring out my
address.
People seem to be able to figure that out just fine, as I get legitimate email all the time. Sometimes the best solutions don't require writing any code. :)
A lightweight way to obfuscate the href of an anchor is to base64-encode it:
> btoa('mailto:email#example.com')
< "bWFpbHRvOmVtYWlsQGV4YW1wbGUuY29t"
And then include it hardcoded:
E-Mail
Or dynamically server-side e.g. in PHP:
E-Mail
In combination with string reversion it could be pretty spam-save:
<?= strrev("email#example.com") ?>
Apparently using CSS to change the direction of your text works pretty well. That link has a test of a bunch of other obfuscation methods as well.
Whatever you use is inevitably going to be defeated. Your primary aim should be to avoid annoying the heck out of your users.
Don't use any obfuscation techniques here because it's probably the first place the email harvesters will look to find out how people are obfuscating emails. If you have to have your email address visible on the site don't just copy verbatim someone else's method; obfuscate it in some unique way that no other site has used so that your method won't be known to harvesters before they visit your site.
mine is actually simple:
<h3 id="email">hello#gmail.com</h3><!-- add a fake email -->
$(document).ready(function(){
//my email in reverse :)
var s = 'moc.elibomajninbew#htiek';
var e = s.split("").reverse().join("");
$('#email').html(''+e+'');
});
You could do as Google do on Google Code (and Groups). Display a par tof the email, and a clickable portion ("..."). Clicking that indicates you want to know the email, and you are asked to fill in a captcha. Afterwards the email (and others?) are visible to you.
One website I maintain uses a somewhat simplistic JavaScript means of (hopefully) keeping spambots out.
Email links call a JS function:
function sendEmail(name, domain) {
location.href = 'mailto:' + name + '#' + domain;
}
To make sure only users who have JS enabled can see the link, write them out with this:
function writeEmailLink(realName, name, domain) {
document.write('<a href="javascript:sendEmail(\''
+ name + '\', \'' + domain + '\')">');
document.write(realName);
document.write('</a>');
}
The use of one JS function to write out a link that calls another means that there are two layers of protection.
I use JavaScript obfuscation, take a look at this one for example:
http://www.jottings.com/obfuscator/
As a poster above said, I also use JavaScript obfuscation from the jottings website.
The web page generates some JavaScript which can be improved on. The mailto: text string is in the clear and identifiable by robots (which could spot this and unobfuscate this string), but if one enters into the jottings.com webpage an email address of the form mailto:addr#site.tld instead of addr#site.tld and then removes the text mailto: from the JavaScript that is generated, one suddenly has some JavaScript that does not look as though it has anything to do with email at all - just random JavaScript of which the web is full. One can improve this still further by getting rid of the link text - I replaced mine by an image of my email address that is in a fairly obscure font. Then just in case this method on jottings.com becomes popular, I randomized the variable names in the output JavaScript to make it hard for a robot to spot an instance of jottings generated JavaScript code.
Obviously some of these improvements could be built into the mechanism on jottings itself, and since the code is openly available this would be relatively easy.
An example may make this a bit more clear. I used the Jottings Obfuscator at the link above to obscure mailto:foo#bar.com (note I am cheating on the original intent of the jottings website by entering the string mailto:foo#bar.com instead of foo#bar.com) with text "Send Me Email", which jottings turned into this Javascript:
<script type="text/javascript" language="javascript">
<!--
// Email obfuscator script 2.1 by Tim Williams, University of Arizona
// Random encryption key feature by Andrew Moulden, Site Engineering Ltd
// This code is freeware provided these four comment lines remain intact
// A wizard to generate this code is at http://www.jottings.com/obfuscator/
{ coded = "3A1OTJ:rJJ#VAK.GJ3"
key = "J0K94NR2SXLupIGqVwt8EZlhznemfaPjs7QvTB6iOyWYo3rAk5FHMdxCg1cDbU"
shift=coded.length
link=""
for (i=0; i<coded.length; i++) {
if (key.indexOf(coded.charAt(i))==-1) {
ltr = coded.charAt(i)
link += (ltr)
}
else {
ltr = (key.indexOf(coded.charAt(i))-shift+key.length) % key.length
link += (key.charAt(ltr))
}
}
document.write("<a href='mailto:"+link+"'>Send Me Email</a>")
}
//-->
</script><noscript>Sorry, you need Javascript on to email me.</noscript>
After I get that back, I paste it into an editor and:
remove the mailto:
replace link text with pointer to an image of my email address
rename all the variables
replace the "noscript" section with another link to the email address image
I end up with this:
<script type="text/javascript" language="javascript">
<!--
// Email obfuscator script 2.1 by Tim Williams, University of Arizona
// Random encryption kkeoy feature by Andrew Moulden, Site Engineering Ltd
// This kudzu is freeware provided these four comment lines remain intact
// A wizard to generate this kudzu is at http://www.jottings.com/obfuscator/
{ kudzu = "3A1OTJ:rJJ#VAK.GJ3"
kkeoy = "J0K94NR2SXLupIGqVwt8EZlhznemfaPjs7QvTB6iOyWYo3rAk5FHMdxCg1cDbU"
shift=kudzu.length
klonk=""
for (variter=0; variter<kudzu.length; variter++) {
if (kkeoy.indexOf(kudzu.charAt(variter))==-1) {
lutu = kudzu.charAt(variter)
klonk += (lutu)
}
else {
lutu = (kkeoy.indexOf(kudzu.charAt(variter))-shift+kkeoy.length) % kkeoy.length
klonk += (kkeoy.charAt(lutu))
}
}
document.write("<a href='"+klonk+"'><img src='contactaddressimage.png' alt='Send Me Email' border='0' height='62' width='240'></a>")
}
//-->
</script>
<noscript>
<img src="contactaddressimage.png" border="0" height="62" width="240">
<font face="Arial" size="3"><br> </font></p>
</noscript>
I don't how well this would work. Could you not leave your email address out and make it load using an AJAX call once the page has finished loading. Not sure if spam bots can pick up the altered HTML or if they are clever enough to listen on other HTTP traffic to try and pick email addresses or if they just scan the page as it is received the first time.
One guy tested nine different ways of presenting an email address on a page and then published results on his blog.
His three best ways were:
Changing the code direction with CSS
Using CSS display:none
ROT13 Encryption
Caveat -- this was posted two years ago. Spam bots might've gotten smarter.
If you work with PHP, you can grab a free script that does that automatically. It's called "Private Daddy" and we use it for our own online audio streaming service. Just one line of code and it works out of the box... you can grab it here
Another approach could be by using a JavaScript framework and binding the data/model to the HTML elements. In the case of AngularJS, the HTML elements would be written as:
<span>{{contactEmail}}</span>
The interpolation {{data}} binding uses a scope variable that contains the actual email value. In addition, a filter could also be used that handles the decoding of the email as follows:
<span>{{contactEmail | decode}}</span>
The benefits are in the way the HTML is written. The downside is that it requires scripting support which some for may be a no no.
just another approach.
Using JQuery, but can easily be ported to plain JS if needed. Will take the following HTML block. This example I provided is also for tel: links for phone calls.
<a class="obfuscate"
href="mailto:archie...trajano...net">
archie...trajano...net
</a>
<a class="obfuscate"
href="tel:+One FourOneSix-EightFiveSix-SixSixFiveFive">
FourOneSix-EightFiveSix-SixSixFiveFive
</a>
and convert it to the proper links using Javascript.
$(".obfuscate").each(function () {
$(this).html($(this).html()
.replace("...", "#").replace(/\.\.\./g, ".")
.replace(/One/g, "1")
.replace(/Two/g, "2")
.replace(/Three/g, "3")
.replace(/Four/g, "4")
.replace(/Five/g, "5")
.replace(/Six/g, "6")
.replace(/Seven/g, "7")
.replace(/Eight/g, "8")
.replace(/Nine/g, "9")
.replace(/Zero/g, "0"))
$(this).attr("href", $(this).attr("href")
.replace("...", "#").replace(/\.\.\./g, ".")
.replace(/One/g, "1")
.replace(/Two/g, "2")
.replace(/Three/g, "3")
.replace(/Four/g, "4")
.replace(/Five/g, "5")
.replace(/Six/g, "6")
.replace(/Seven/g, "7")
.replace(/Eight/g, "8")
.replace(/Nine/g, "9")
.replace(/Zero/g, "0"))
})
I documented it in more detail here https://trajano.net/2017/01/obfuscating-mailto-links/
The de/obfuscation algorithm is pretty simple so its not too taxing to write either (no need for base64 parsing)
The Ajax call solution
The best is to have a form on the website and not to show email address, because all robots are more intelligent day after day, but if you need to show email address on the website, so, you can make it with ajax call on your server, and show it on click.
HTML
<a class="obfmail" href="#" rel="info">click here to show email address</a>
or
<a class="obfmail" href="#" rel="info">
<img src="img/click-to-show-email.jpg">
</a>
jQuery
$(document).one'click', '.obfmail', function(e) {
e.preventDefault();
a = $(this);
addr = a.attr('rel');
$.ajax({
data: {
email: addr
},
url : "/a/getemail",
type: "POST",
dataType: 'json',
success: function(data) {
a.html(data.addr);
a.attr('href', 'mailto:' + data.addr);
}
});
});
PHP
if($_POST['email']) {
...
return json_encode(array(
code => '200',
response => 'success',
addr => 'info#domain.ltd'
));
}
For more security, you can change .on by .one like this $(document).one('click', '.obfmail', function(e) { or even work with a PHP generated token that you pass into data on ajax call, to accept only one call of the ajax function like this :
html: <a class="obfmail" href="#" rel="info" token="w3487ghdr6rc">
jquery:
...
addr = a.attr('rel');
tkn = a.attr('token');
$.ajax({
data: {
email: addr,
token: tkn
}, ...
.
It is possible to encode the returned email address too or invert it.
.
Working fine for phone numbers too !
Cloudflare is now offering free email obfuscation service. This might be an option if you use Cloudlfare.
I agree with #srobinson in that using an online form for encoding to html entities seems a little shady. A few lines of python will do it for you:
def htmlEntities( string ):
return ''.join(['&#{0};'.format(ord(char)) for char in string])
htmlEntities("barnstable#example.com")
the above returns:
'barnstable#example.com'
Which is barnstable#example.com encoded to HTML Entities (surrounded by single quotes).
Honestly, your problem may be moot if you asked the question of whether or not a mailto is really what you want to use. A lot of people who use web mail, for example, or do not have the proper mail client setup in their browser are not going to benefit from a mailto. You are exposing your email address for a function that isn't going to work for a large portion of your users.
What you could do instead is use a form to send the e-mail behind the scenes so that the e-mail address is hidden and you don't have to worry about the poor saps who won't benefit from a mailto.
If you say on your site that "My e-mail address is (my first name)#(my last name).com.", and your first name and last name are pretty darn obvious, that seems to be the best spam protection you're going to get.
If anyone's using Rails, they can use the actionview-encoded_mail_to gem. (https://github.com/reed/actionview-encoded_mail_to)
There are a few options:
:encode - This key will accept the strings "javascript" or "hex".
Passing "javascript" will dynamically create and encode the mailto
link then eval it into the DOM of the page. This method will not show
the link on the page if the user has JavaScript disabled. Passing
"hex" will hex encode the email_address before outputting the mailto
link.
:replace_at - When the link name isn't provided, the
email_address is used for the link label. You can use this option to
obfuscate the email_address by substituting the # sign with the string
given as the value.
:replace_dot - When the link name isn't provided,
the email_address is used for the link label. You can use this option
to obfuscate the email_address by substituting the . in the email with
the string given as the value.
<!-- Multi-Email Obfuscator -->
<!-- step 1: # = # -->
<!-- step 2: a scrap element -->
<!-- step 3: ROT13 encode for .com -->
info<!-- step 1 -->#<!-- step 2 --><b style="display:none">my</b>domain<!-- step 3 --><script>document.write(".pbz".replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);}));</script>
Since this solution is not mentioned anywhere, but works well for me:
I do this:
create a mailto link with fake email. I like admin#localhost.localdomain for obvious reasons: Spammer might spam his own botnet when using this address unchecked.
cypher real email address and put it in an unrelated but findable hidden span or whatever element you like. Obviously to obfuscate the email and hide it from the harvester. Depending on your project structure, you might even want to put it in a JS or Session variable.
create a click handler for these links after a second that decyphers and write the correct email address into the fake mailto link not preventing defaults.
I do not think that crawlers click on mailto links, but if they would, they probaby won't wait a second, while a human being would have to be extremly fast to click a link in the first second after pageload.
Now you have a fully functional but obfuscated, honeypoted and timesecured mailto link.
Working example php file:
<html>
<head>
<title>E-Mail Obfuscating</title>
</head>
<body>
<?php
$email = "example#email.org";
echo "<a class='emailLink' href='mailto:admin#localhost.localdomain' >Send me an e-mail!</a>"
."<span style='display:none' data-hash='" . base64_encode($email) . "' />";
?>
<script>
<!--
var emailLinks = document.getElementsByClassName("emailLink");
setTimeout(function() {
for(var i=0; i <emailLinks.length; ++i){
emailLinks[i].addEventListener("click", function(){
let encodedEmail = this.nextSibling.getAttribute('data-hash');
let decodedEmail = atob(encodedEmail);
this.href = "mailto:" + decodedEmail;
this.text = decodedEmail;
});
}
}, 1000);
-->
</script>
</body>
</html>
May the code be with you.
What if creating a link "Contact me" pointing to a directory protected by a password? Of course, you have to give the pass to access.
"Contact me" > ••••••••••• > contact/index.html
Once accessed, the contact/index.html page reveals the email, a mailto for instance.
My solution is to rearrange the characters using css and replacing the element on hover. No change is visible to the user.
const obscureHoverReverseMailTo = input => `<span style="display: inline-flex; color: rgb(0, 0, 238); cursor: pointer; text-decoration: underline;" onmouseover="const newContent = [...this.children].sort((a, b) => a.style.order - b.style.order).map(el => el.innerText).join('');this.outerHTML = \`<a href='mailto: \${newContent}'>\${newContent}</a>\`">${input.split("").map((char, index) => `<span style="order: ${index}">${char}</span>`).sort(() => 0.5 - Math.random()).join("")}</span>`;
const obscureHoverReverseMailTo = input => `<span style="display: inline-flex; color: rgb(0, 0, 238); cursor: pointer; text-decoration: underline;" onmouseover="const newContent = [...this.children].sort((a, b) => a.style.order - b.style.order).map(el => el.innerText).join('');this.outerHTML = \`<a href='mailto: \${newContent}'>\${newContent}</a>\`">${input.split("").map((char, index) => `<span style="order: ${index}">${char}</span>`).sort(() => 0.5 - Math.random()).join("")}</span>`;
document.getElementById("testRoot").innerHTML = obscureHoverReverseMailTo("hello#example.com")
<div id="testRoot"></div>
<input type="text" onkeyup="document.getElementById('testOut').innerHTML = obscureHoverReverseMailTo(this.value)">
<div id="testOut"></div>
here is the function if you have something else to hide:
const obscureHoverReverse = input => `<span style="display: inline-flex" onmouseover="this.outerHTML = [...this.children].sort((a, b) => a.style.order - b.style.order).map(el => el.innerText).join('')">${input.split("").map((char, index) => `<span style="order: ${index}">${char}</span>`).sort(() => 0.5 - Math.random()).join("")}</span>`;
Simple JavaScript-unaware bots typically look for mailto: and/or # in HTML page contents. Obfuscating these keywords will dramatically decrease chances of email address scraping.
A Base-64 encoded URL template mailto:%user%#%domain% can be employed:
function contact(user, domain = location.hostname) {
const template = atob('bWFpbHRvOiV1c2VyJUAlZG9tYWluJQ==');
location.href = template
.replace('%user%', user)
.replace('%domain%', domain);
return false;
}
Where 'bWFpbHRvOiV1c2VyJUAlZG9tYWluJQ==' is btoa('mailto:%user%#%domain%').
HTML links would need to be updated as follows:
e-mail me
Furthermore, javascript: addresses can be hidden from the users:
e-mail me
The return statements prevent the page navigation to the # anchor.
I use a PHP function to generate some javascript to output the email on page load. Note that you don't need PHP to generate the JS at runtime, you can generate the JS once locally and then include the static JS in your page.
You can also use the linked function with this snippet below to automatically obfuscate email addresses in some given HTML (where $processedContent is the HTML):
$emailMatches = array();
$matchCount = preg_match_all('/(?:[a-zA-Z0-9_\.\-])+\#(?:(?:[a-zA-Z0-9\-])+\.)+(?:[a-zA-Z0-9]{2,4})+/', $processedContent, $emailMatches);
if($matchCount > 0) {
$emailMatches = $emailMatches[0];
foreach($emailMatches as $email) {
$replacement = createJSMailLink($email);
$processedContent = str_replace($email, createJSMailLink($email), $processedContent);
}

Categories