Google recently released an extension that would allow for users to specify ‘spam’ search results. Kynetx wants to take that a step further with an application that will do the same thing in Firefox and Internet Explorer as well as Chrome. The application had to be built in 24 hours. I always like a good challenge and learning something new, so I took a stab at it.
I wanted to keep the minimalistic idea that Google had with their extension, but make it more visible and useable. When you hover over a search result an option to remove the result is presented.
A notify box stays in the top right of the screen. It tells how many items are being hidden, and you can un-hide them.
Once items are un-hidden, you can choose to restore the result.
While developing, I kept running into problems where the entity variables didn’t stay. I am sure it was because I have a horrible habit of hard-refreshing the browser. So, I thought it would be nice to link the urls I want to exclude to a google spreadsheet. For this to work, there are two keys from the google spreadsheet to put into the app. Linking to a Google doc is optional, it is just nice that when my cookies are reset or cleaned, I don’t have to start over again removing search results.
Log into google docs and create a new spreadsheet. First create a new form. It only needs one field and it doesn’t matter what the name is. This is a screenshot of my completed form.
After creating the form, this is what my spreadsheet looked like. (I couldn’t figure out how to get rid of the timestamp, but with the 24 hour time limit, I didn’t worry about it too much)
The last think you need to do to set up the spreadsheet is to publish it. In the upper-right corner of the screen click the down arrow next to share and select “Publish as a web page”. Start Publishing:
Copy the google spreadsheet key (highlighted in picture below), and paste it into the first box (see the third picture of this post)
The last part is the form Key. In the google spreadsheet click on form, and then “Go to live form”. Copy the formkey from the url (highlighted in picture below)
The application will now add the urls you decide to remove to the google spreadsheet. And the urls in the spreadsheet will be used to remove search results. So on the off chance your urls aren’t working, you just have to add the google spreadsheet keys, instead of add all the urls again. Another nice thing is you can just add urls that you know are spam. The only down side, is that when you want to stop removing a url from the search results, you have to remove the url from the spreadsheet manually.
I am impressed with the changes to the search annotation that Kynetx has made. It is much easier to use and customize.
Below are the browser extensions. Please download and try. Leave a comment, I would love feedback!
I am adding the bookmarklet as well because it seems to work better in some cases than the extension. Hoogleing
Known Issues: Can’t restore a search result in IE. Yahoo doesn’t seem to work as well. Sometimes google doesn’t refresh the page and hide elements after they have been removed(disable instantSearch)
After spending 2 hours working on IE I gave up. I could have figured it out with more time, but the debug tools on IE suck… oh wait… there aren’t any! I think I am going to join an anti-develop-for-IE group.
ruleset a279x11 {
meta {
name "Hoogleing"
description >>
<<
author "David"
logging off
}
dispatch {
domain "google.com"
domain "bing.com"
domain "yahoo.com"
}
global {
//set the datasource for the google spreadsheet if the key is supplied in the app
datasource googleSheets >- "https://spreadsheets.google.com/"
css >>
.restoreResultKRL { visibility:visible; float:right; background-color: white; background-image: url(http://davidgodfrey.info/images/search/myCheck.png); background-repeat: no-repeat; border: medium none; padding-left: 20px; cursor: pointer; }
.removeResultKRL { visibility:hidden; float:right; background-color: white; background-image: url(http://davidgodfrey.info/images/search/myX.png); background-repeat: no-repeat; border: medium none; padding-left: 20px; cursor: pointer; }
.removeResultKRL,
.restoreResultKRL { background-color: #fffddd; padding: 5px 5px 5px 20px; background-position: 2px 4px; border: 1px solid #efefef; }
.SPAMremove:hover .restoreResultKRL,
.SPAMremove:hover .removeResultKRL { visibility:visible }
<<;
}
//This rule sets up the notify box at the top right of the screen
rule first_rule is active {
select using "google.com|bing.com/search|search.yahoo.com/search" setting()
pre {
message = >>
>span id="spamSearchCatcher"<0>/span< search results removed.>br /<>br /<
>button type="button" id="spanSeeRemoved" style="display:none; background: none; background-image: url(http://davidgodfrey.info/images/search/restoreA.png); background-repeat: no-repeat; border: medium none; padding-left: 20px; cursor: pointer; color: #68b4ef;"<See removed results>/button<>br /<>br /<
>button type="button" id="SPAMexternalGoogle" style="background: none; background-image: url(http://davidgodfrey.info/images/search/google.png); background-repeat: no-repeat; border: medium none; padding-left: 20px; cursor: pointer; color: #56c42e;"<Google Spreadsheet settings>/button<>br /<
>span id="showExternalGoogle" style="display:none;"<
>label<Google Spreadsheet Key>/label<>br /<>input style="margin: 5px 0 10px 0;" id="SPAMGoogleKey" type="text"<>/input<>br /<
>label<Google Form Key>/label<>br /<>input style="margin: 5px 0 10px 0;" id="SPAMGoogleFormKey" type="text"<>/input<>br /<
>button id="SPAMsubmitGoogleInfo" type="button"<Save>/button<
>/span<
>br /<
>span id="SPAMremoveNotice" style="display:none;"<It looks like you are using a Google Spreadsheet! To restore a result, you will have to remove the row from the Google Spreadsheet manually.>/span<
<<;
}
emit >|
$K('#spanSeeRemoved').live('click', function(){
$K('.SPAMremove').show();
//$K('#spanSeeRemoved').fadeOut();
});
$K('#SPAMexternalGoogle').live('click', function(){
$K('#showExternalGoogle').toggle();
});
|<
notify("", message) with sticky = true;
}
rule search_annotate_rule is active {
select using "google.com|bing.com/search|search.yahoo.com/search" setting()
pre {
//the variable that will hold the removed sites.
sites = ent:my_sites;
//get the google spreadsheet key and then get the csv
gKey = ent:my_gKey;
csvFromGoogleDoc = datasource:googleSheets("pub?hl=en&hl=en&key=" + gKey + "&single=true&gid=0&output=csv");
}
emit >|
//split the csv into a javascript array
if(csvFromGoogleDoc.length < 20){
var tempString = csvFromGoogleDoc.replace(/(\r\n|[\r\n])/g, ",");
var googleValues = tempString.split(',');
$K('#SPAMremoveNotice').show();
}else{
var googleValues = [0];
}
|<
every {
emit >|
function annotate_spamRemove(toAnnotate, wrapper, data) {
if ($K.inArray(data.domain, sites) != -1 || $K.inArray(data.domain, googleValues) != -1) {
toAnnotate.hide();
$K('#spamSearchCatcher').html(($K('#spamSearchCatcher').html()*1)+1);
$K('#spanSeeRemoved').show();
wrapper.append(">button type='button' domain='"+data.domain+"' class='restoreResultKRL'<restore result>/button<");
wrapper.show();
}else{
wrapper.append(">button type='button' domain='"+data.domain+"' class='removeResultKRL'<remove result>/button<");
wrapper.show();
}
toAnnotate.addClass('SPAMremove');
}
app = KOBJ.get_application("a279x11");
$K('.removeResultKRL').live('click', function(){
theDomain = $K(this).attr('domain');
$K(this).removeClass('removeResultKRL').addClass('restoreResultKRL').text('removed');
$K(this).closest('.SPAMremove').delay(1000).fadeOut('fast', function(){$K('.restoreResultKRL').text('restore result');});
app.raise_event("remove_result_from_search", {"myDomain":theDomain});
});
$K('.restoreResultKRL').live('click', function(){
theDomain = $K(this).attr('domain');
$K(this).addClass('removeResultKRL').removeClass('restoreResultKRL').text('remove result');
app.raise_event("restore_result_from_search", {"myDomain":theDomain});
});
$K('#SPAMsubmitGoogleInfo').live('click', function(){
$K('#SPAMsubmitGoogleInfo').text('Saved').attr('disabled', 'disabled');
googleKey = $K('#SPAMGoogleKey').val();
googleFormKey = $K('#SPAMGoogleFormKey').val();
app.raise_event("store_google_keys", {"Gkey":googleKey, "GFkey":googleFormKey});
});
|<;
annotate:annotate("SPAMremove") with annotator = >| annotate_spamRemove |<;
}
}
rule custom_event_for_removing_result {
select when web remove_result_from_search
pre {
gKey = ent:my_gKey;
gfKey = ent:my_gfKey;
sites = ent:my_sites;
domain = event:param("myDomain");
new_array = sites.union(domain);
}
emit >|
if(gKey.length < 20 && gfKey.length < 20){
app = KOBJ.get_application("a279x11");
app.raise_event("save_in_google", {"myDomain":domain });
}
|<
fired {
set ent:my_sites new_array;
}
}
rule custom_event_for_restoring_result {
select when web restore_result_from_search
pre {
sites = ent:my_sites;
domain = event:param("myDomain");
new_array = sites.difference(domain);
}
fired {
set ent:my_sites new_array;
}
}
rule custom_event_store_google_keys {
select when web store_google_keys
pre {
gKey = event:param("Gkey");
gfKey = event:param("GFkey");
}
fired {
set ent:my_gKey gKey;
set ent:my_gfKey gfKey;
}
}
rule custom_event_save_in_google {
select when web save_in_google
pre {
domain = event:param("myDomain");
gfKey = ent:my_gfKey;
}
{
http:post("https://spreadsheets.google.com/formResponse?hl=en&formkey=" + gfKey + "&ifq") with params = { "entry.0.single":domain, "submit":"Submit", "pageNumber":"0", "backupCache":"" };
}
}
}
Beating Google
Google recently released an extension that would allow for users to specify ‘spam’ search results. Kynetx wants to take that a step further with an application that will do the same thing in Firefox and Internet Explorer as well as Chrome. The application had to be built in 24 hours. I always like a good challenge and learning something new, so I took a stab at it.
I wanted to keep the minimalistic idea that Google had with their extension, but make it more visible and useable. When you hover over a search result an option to remove the result is presented.
Internet Explorer Extension
Firefox Extension
Chrome Extension
Can’t restore a search result in IE.
Yahoo doesn’t seem to work as well.
Sometimes google doesn’t refresh the page and hide elements after they have been removed(disable instantSearch)
After spending 2 hours working on IE I gave up. I could have figured it out with more time, but the debug tools on IE suck… oh wait… there aren’t any! I think I am going to join an anti-develop-for-IE group.
ruleset a279x11 {
meta {
name "Hoogleing"
description >>
<<
author "David"
logging off
}
dispatch {
domain "google.com"
domain "bing.com"
domain "yahoo.com"
}
global {
//set the datasource for the google spreadsheet if the key is supplied in the app
datasource googleSheets >- "https://spreadsheets.google.com/"
css >>
.restoreResultKRL { visibility:visible; float:right; background-color: white; background-image: url(http://davidgodfrey.info/images/search/myCheck.png); background-repeat: no-repeat; border: medium none; padding-left: 20px; cursor: pointer; }
.removeResultKRL { visibility:hidden; float:right; background-color: white; background-image: url(http://davidgodfrey.info/images/search/myX.png); background-repeat: no-repeat; border: medium none; padding-left: 20px; cursor: pointer; }
.removeResultKRL,
.restoreResultKRL { background-color: #fffddd; padding: 5px 5px 5px 20px; background-position: 2px 4px; border: 1px solid #efefef; }
.SPAMremove:hover .restoreResultKRL,
.SPAMremove:hover .removeResultKRL { visibility:visible }
<<;
}
//This rule sets up the notify box at the top right of the screen
rule first_rule is active {
select using "google.com|bing.com/search|search.yahoo.com/search" setting()
pre {
message = >>
>span id="spamSearchCatcher"<0>/span< search results removed.>br /<>br /<
>button type="button" id="spanSeeRemoved" style="display:none; background: none; background-image: url(http://davidgodfrey.info/images/search/restoreA.png); background-repeat: no-repeat; border: medium none; padding-left: 20px; cursor: pointer; color: #68b4ef;"<See removed results>/button<>br /<>br /<
>button type="button" id="SPAMexternalGoogle" style="background: none; background-image: url(http://davidgodfrey.info/images/search/google.png); background-repeat: no-repeat; border: medium none; padding-left: 20px; cursor: pointer; color: #56c42e;"<Google Spreadsheet settings>/button<>br /<
>span id="showExternalGoogle" style="display:none;"<
>label<Google Spreadsheet Key>/label<>br /<>input style="margin: 5px 0 10px 0;" id="SPAMGoogleKey" type="text"<>/input<>br /<
>label<Google Form Key>/label<>br /<>input style="margin: 5px 0 10px 0;" id="SPAMGoogleFormKey" type="text"<>/input<>br /<
>button id="SPAMsubmitGoogleInfo" type="button"<Save>/button<
>/span<
>br /<
>span id="SPAMremoveNotice" style="display:none;"<It looks like you are using a Google Spreadsheet! To restore a result, you will have to remove the row from the Google Spreadsheet manually.>/span<
<<;
}
emit >|
$K('#spanSeeRemoved').live('click', function(){
$K('.SPAMremove').show();
//$K('#spanSeeRemoved').fadeOut();
});
$K('#SPAMexternalGoogle').live('click', function(){
$K('#showExternalGoogle').toggle();
});
|<
notify("", message) with sticky = true;
}
rule search_annotate_rule is active {
select using "google.com|bing.com/search|search.yahoo.com/search" setting()
pre {
//the variable that will hold the removed sites.
sites = ent:my_sites;
//get the google spreadsheet key and then get the csv
gKey = ent:my_gKey;
csvFromGoogleDoc = datasource:googleSheets("pub?hl=en&hl=en&key=" + gKey + "&single=true&gid=0&output=csv");
}
emit >|
//split the csv into a javascript array
if(csvFromGoogleDoc.length < 20){
var tempString = csvFromGoogleDoc.replace(/(\r\n|[\r\n])/g, ",");
var googleValues = tempString.split(',');
$K('#SPAMremoveNotice').show();
}else{
var googleValues = [0];
}
|<
every {
emit >|
function annotate_spamRemove(toAnnotate, wrapper, data) {
if ($K.inArray(data.domain, sites) != -1 || $K.inArray(data.domain, googleValues) != -1) {
toAnnotate.hide();
$K('#spamSearchCatcher').html(($K('#spamSearchCatcher').html()*1)+1);
$K('#spanSeeRemoved').show();
wrapper.append(">button type='button' domain='"+data.domain+"' class='restoreResultKRL'<restore result>/button<");
wrapper.show();
}else{
wrapper.append(">button type='button' domain='"+data.domain+"' class='removeResultKRL'<remove result>/button<");
wrapper.show();
}
toAnnotate.addClass('SPAMremove');
}
app = KOBJ.get_application("a279x11");
$K('.removeResultKRL').live('click', function(){
theDomain = $K(this).attr('domain');
$K(this).removeClass('removeResultKRL').addClass('restoreResultKRL').text('removed');
$K(this).closest('.SPAMremove').delay(1000).fadeOut('fast', function(){$K('.restoreResultKRL').text('restore result');});
app.raise_event("remove_result_from_search", {"myDomain":theDomain});
});
$K('.restoreResultKRL').live('click', function(){
theDomain = $K(this).attr('domain');
$K(this).addClass('removeResultKRL').removeClass('restoreResultKRL').text('remove result');
app.raise_event("restore_result_from_search", {"myDomain":theDomain});
});
$K('#SPAMsubmitGoogleInfo').live('click', function(){
$K('#SPAMsubmitGoogleInfo').text('Saved').attr('disabled', 'disabled');
googleKey = $K('#SPAMGoogleKey').val();
googleFormKey = $K('#SPAMGoogleFormKey').val();
app.raise_event("store_google_keys", {"Gkey":googleKey, "GFkey":googleFormKey});
});
|<;
annotate:annotate("SPAMremove") with annotator = >| annotate_spamRemove |<;
}
}
rule custom_event_for_removing_result {
select when web remove_result_from_search
pre {
gKey = ent:my_gKey;
gfKey = ent:my_gfKey;
sites = ent:my_sites;
domain = event:param("myDomain");
new_array = sites.union(domain);
}
emit >|
if(gKey.length < 20 && gfKey.length < 20){
app = KOBJ.get_application("a279x11");
app.raise_event("save_in_google", {"myDomain":domain });
}
|<
fired {
set ent:my_sites new_array;
}
}
rule custom_event_for_restoring_result {
select when web restore_result_from_search
pre {
sites = ent:my_sites;
domain = event:param("myDomain");
new_array = sites.difference(domain);
}
fired {
set ent:my_sites new_array;
}
}
rule custom_event_store_google_keys {
select when web store_google_keys
pre {
gKey = event:param("Gkey");
gfKey = event:param("GFkey");
}
fired {
set ent:my_gKey gKey;
set ent:my_gfKey gfKey;
}
}
rule custom_event_save_in_google {
select when web save_in_google
pre {
domain = event:param("myDomain");
gfKey = ent:my_gfKey;
}
{
http:post("https://spreadsheets.google.com/formResponse?hl=en&formkey=" + gfKey + "&ifq") with params = { "entry.0.single":domain, "submit":"Submit", "pageNumber":"0", "backupCache":"" };
}
}
}