Sunday, November 2, 2014

Advertising with Google: It Sucks

Advertising with Google as a small business is much different than using Google as a consumer. Paying Google for ads and calling Google support is a lot like paying Comcast for cable and calling Comcast support

The events described in this post happened about a year ago. I finally decided to make this post for two reasons: to show that Google is exactly like every other large faceless near-monopoly and to show my disappointment with how Google handles paying customers. 

Before this experience, I thought the parts of Google that make money must be amazing. Look at Gmail, Google Docs Drive, Google Calendar, Blogger and even Android. They’re great, and they’re all free. Google makes these services to capture you, the product. If the free stuff is great, then the parts of Google that face advertisers (the customer) and take in billions of dollars in revenue have to be absolutely amazing. Sadly, they’re not.

Lets start with some background. A year ago I had a great idea: start a website that would sort pocket knives by legality to carry. You would pick a city and see knives that are legal to carry in that jurisdiction. The list of knives have Amazon referral links. Everyone would benefit: the customers would stay legal, and I would collect a sales commission. 

The story of the site is long and deserves its own blog post, but in summary... creating product sales sites is hard. The site I made, legalknifeshop.com, is still up. Go and take a look, and if you live in Chicago, order a knife. Also, I know the site has many problems. I’ve been too busy to work on it. If you see something wrong, I’m probably aware of it but don’t have time to fix anything.

But this post is about advertising, so lets get back to the story. The first order of business after making a site is to advertise. There is only one choice in online advertising: Google. I signed up for an AdWords account, selected keywords, and paid money. Legalknifeshop was approved and the ads started. Time to wait for the sales to roll in!  

The ads ran for two days. Then I got the first email. 
Urgent Warning - Your AdWords Account May Get Suspended

That's not good. It turns out that after being approved, legalknifeshop was unapproved, despite no content changes.

The site was in violation of the weapons policy that prohibits dangerous knives. The violation was silly: legalknifeshop only sells explicitly legal knives, and knives legal to carry in Chicago (the only supported location) must have <2.5" blade. Boy scouts handle longer and more dangerous knives. Certainly someone at Google could understand and reinstate the ads. 

I called Google support. After 4 different menu prompts there was a human, to whom I explained the situation. 

She put me on hold for 15 minutes, came back and said that she “had no idea what was going on,” but the site needed to be escalated back to review”. “But what about the previous review,” I asked. “I don’t work in that department,” she answered. 

This was the first sign of what was to come.

Then another email. 
Your AdWords account: Ads not running due to AdWords Advertising Policies.

Maybe the review department wasn’t convinced? Having heard nothing else, I sent a support an email asking why legalknifeshop violated the weapons policy.
Call 1-866-2-GOOGLE* for free expert help reviewing your AdWords ads 

That was the title of the next email. It continued: "Having reviewed your AdWords account XXXXXXXXXX, we can see that so far 549 potential customers have seen your ad, and 4 of them clicked on your ad to view your website. We can help you attract more potential customers to your website or answer any other questions you may have".

Maybe they could start by reinstating my ads?  Really, Google? What world do we live in when a Big Data company like Google can't link their suspended account database to their promotional emails?

I called support again and spent 20 minutes on hold. The reply was "oh, I can't really see what's going on, you'll have to contact the people who you were contacting before". This is when I knew I was in trouble. There isn’t even a coherent customer records management or issue tracking.

During the next few weeks I called, used the online customer chat, and sent emails. Finally, after persevering and explaining that legalknifeshop sold no dangerous knives, someone at Google admitted that no, legalknifeshop does not violate the weapons policy. Victory at last! 

The sweet taste of victory was not to last.

The next day, another suspension email. Now, my site was in violation of the bridge page policy. A policy that was not mentioned once during the many prior discussions with Google support. I appealed again, but it was not to be.

It turns out that legalknifeshop doesn't provide enough value to end users. To provide enough value to advertise with Google requires the following changes:
  • Provide listings for more than one city (doable)
  • and one of:
  • Use more than Amazon as a referral partner. (pretty much impossible)
  • or
  • Sell the knives myself. (impossible)

During my new week of appeals, I received the following promotions from Google:
Reach the right customers by adding negative keywords to your AdWords ad 'Knives Legal In Chicago'

Your AdWords ads have stopped running. Talk to Google to get help. Remember to call 1-866-2-GOOGLE* for a free review of your AdWords ads with a Google expert

There is no way I could meet the bridge page requirements. Google won, they refused to take my money. I really tried to pay, but they just wouldn’t take it.

Two days later, there was one last email:
AdWords Tune-up: Make your 'LegalKnifeShop #1' campaign ad stand out with a longer headline

That was the last straw. Out of pure spite, I advertised with Bing. But that's a story for another blog post.

Sunday, May 18, 2014

What Happens When Your Phone Falls into the Ocean

Short answer: It'll stop working.

But have you wondered, why? What happens to the insides of the phone?

We've all heard that salt water conducts electricity and "fries" your electronics, but what does that mean? Will the phone rust? Will the battery melt? Today we get to find out!

In this blog post we'll look inside my Black 16GB iPhone 5 (yes, that's an affiliate link) that took a swim in the Pacific. Where possible, iFixit's iPhone 5 teardown pictures will model what iPhone 5 internals should look like.

The Initial Opening


This is how an iPhone 5 looks like after swimming in the Pacific.
This is how iPhone 5 innards should look like, courtsey of iFixit.

Right away, there's a huge difference. There ocean phone is full of fine sand, salt stains, and a giant rust spot. If you remember chemistry class, then the rust spot makes sense: rust is an electrical process. The biggest rust spot will be at the anode of the battery leads, which is exactly where it is.

The Screen Assembly and Mainboard


The salted, rusty screen assembly. The rust feels like its simply rubbed off from the other part.
The salted, rusty mainboard and battery. The battery is surprisingly intact.
How an iPhone 5 screen assembly and mainboard should look like. Notice the distinct lack of salt, rust, and sand. Courtesy of iFixit.

Once again, the salt stains and rust is the big difference. Surprisingly, the lithium-ion battery is perfectly intact, without holes or burn damage. Why surprising? Lithium and water tend to react vigorously.

Battery Closeup


The battery leads are extra rusty.
An unsalted battery, courtesy of iFixit.

Other than the rusty leads, the battery seems fine from the outside. The phone would not power on, but I am not sure if its related to the battery or other electronics failures. Probably both.

Mainboard and Chassis Closeup


There's a large salt deposit under the mainboard.
The salt water must have pooled there as the phone dried. 
A pristine mainboard, courtesy of iFixit.

Getting to this part was a challenge: some of the screws were so corroded and rusted that unscrewing them stripped the grooves used for unscrewing. I had to resort to force and some prying, which didn't matter since the phone was already broken.

A Zoom on the Mainboard


A zoom on the corroded mainboard.
The front of the camera and mainboard.
A pristine mainboard, courtesy of iFixit.

Almost every connector is rusted or otherwise corroded. This is one of the main reason everything stops working: the small connectors corrode and the mainboard components can't make electrical contact.

Everything


All the rusted components in one glorious photo.
All the pristine components, courtesy of iFixit.

The obligatory "all components in one photo" shot. Mine isn't as nice as iFixit's, but the other differences should be obvious. The one interesting thing to note is the serious corrosion on the SIM card.

Conclusion


If your phone falls into the ocean, its going to have a bad time. Don't let your phone fall into the ocean.

Thursday, May 15, 2014

Bjarne Stroustrup on the Past and Future of C++ (Including Long Template Errors)

Someone on IRC pointed me to Bjarne Stroustrup's talk on C++11 and C++14 at Microsoft's Going Native 2013. If you work with C++ and haven't seen Bjarne's talk yet, go watch it now.

Stop reading this and go. I'll wait. 

An hour into the talk, Bjarne starts discussing templates, long error messages, and the tradeoffs that were made during the design of C++. The long error messages were a conscious decision to preserve performance and expressiveness with the computing power available back in the mid 1980s.

It amazed me that Bjarne admits template error messages are a huge debacle, and he has been working for 20 years to fix the problem. The solution is near: C++14 concepts will finally allow for sane template errors. Messages like "Member must be CopyAssignable" will be possible, and hopefully normal. This isn't just theory: there is an experimental branch of GCC that supports concepts right now.

Other parts of the talk are fascinating in their own right and have given me a lot more respect for C++ and Bjarne Stroustrup. The man could have rested after creating the original C++ spec and compiler, but he has been working for 20 years to improve the language. That dedication has made C++11 much better than C++98.

Bjarne also brings up a good point: many people who dislike C++ are using it the wrong way. The language should only be used when you need a performance and lightweight abstraction at the same time. If you don't care about performance or you need high-level abstraction, C++ is the wrong tool for the job.

The talk has a lot more interesting content. If you haven't watched it yet, go now.

Sunday, May 11, 2014

C++11: better, but still frustrating


Update: jduck pointed out that the before/after code snippets were identical. Oops. Now fixed.

I'd previously given up on C++ due to the many small frustrations: incomprehensible error messages, silly parsing issues (e.g. '>>'), rules to avoid subtle errors, and many other small frustrations that soured me on the language. That was back in the days of C++98 and C++03.

The language has evolved, and recently I found myself working on a project written in C++11. So far my experience has been better, but still frustrating.

A Motivating Example


I'll start with a real example. The project created a lot of Foo objects that were passed by reference to numerous functions. I needed to keep a collection of every Foo object that was passed to a specific function.

My first thought was, "I know, I'll create a vector of Foo&". This thought is simple, elegant, and of course, wrong.

A vector of references isn't possible because references can't be reassigned. That is, references[0] = foo; would update the referenced object, not the zeroth entry of the references vector. More technically, references are not CopyAssignable, a requirement for members of containers.

Errors Galore


But how would someone new to C++ know this? What do compilers say when making a vector of references? Lets find out by compiling this small (and wrong) program.

#include <vector>
#include <iostream>

int main(int argc, const char* argv[])
{
    int a = 1;
    std::vector<int&> test = {a};
    std::cout << "a: " << test[0] << std::endl;
    return 0;
}

Here are the results for Clang, GCC and MSVC:

Compiler Error List Error Count
Clang rextester.com/JMFGP72087 158 lines
GCC rextester.com/HGKFIT84222 187 lines
MSVC rextester.com/UXPG39365 107 lines

In classic C++ style, the error messages are hundreds of error lines from obscure library implementation code. They give no indication of what is wrong, and no indication of the solution. I pity someone who doesn't have C++ experience trying to figure out what is wrong with their code. Pretty much any error would be more helpful, even an obscure message like "Member must be CopyAssignable" -- as long as it pointed out the correct line of code.

The Fix


For reference, the corrected program is:

#include <vector>
#include <iostream>
#include <functional>

int main(int argc, const char* argv[])
{
    int a = 1;
    std::vector<std::reference_wrapper<int>> test = {a};
    std::cout << "a: " << test[0] << std::endl;
    return 0;
}

The fix is to use the std::reference_wrapper utility function when making a container of references.

Conclusion


There's definitely upsides: the '>>' parse has finally been fixed. Classes can now be initialized with initializer lists. There is type inference via 'auto'. For-each style loops exist.

C++11 is a great improvement over C++03, but its still frustrating: the obvious solution (like containers of references) is wrong in subtle ways, and compilers still generate hundreds of obscure error messages for a one-character typo.

Tuesday, May 6, 2014

Do Not Reply Addresses Suck

If you send emails from do not reply addresses, I hate you.
Your customers hate you.
People you've never met also hate you.

Why  you should stop using no reply addresses:
  • Something will go wrong and your customers can't tell you.
  • You will send email to people who aren't your customers. They will have no way to ask you to stop.
Stop hating your current and future customers. Stop using no reply addresses. Only send email from monitored email addresses.

And one more thing...

If you create accounts without validating email addresses, I doubly hate you... and from now on I will be naming and shaming.

The Do Not Reply Hall of Shame


Ask.fm


Ask.fm lets people register without validating their email. The many follow-up emails are all from noreply@ask.fm. Ask.fm, please stop.

As you can guess, nothing was ever done. Ask.fm, I hate you.

DataViz.com


DataViz lets people buy software without verifying their email. Wish I could reply and tell them, but the email is from do-not-reply@dataviz.com.

My name is not Artem Dubov and I did not buy this software.


Saturday, February 8, 2014

Direct Download Link For Adobe Flash Player

Are you tired of seeing this?

"Error: Unable to proceed with the installation". Thats bad. But there's a green checkmark. Thats good? 

Do you find Adobe's toubleshooting page completely useless?
 
Then use this handy direct link and bypass Adobe's broken installer. As a bonus, it wont try to trick you into installing Lightroom or other unwanted products.


Update as of November 2nd, 2014:

Jerry Leichter very helpfully pointed out that Adobe maintains an official redistributable version of Flash player that doesn't use the awful installer. You can get it here:

https://www.adobe.com/products/flashplayer/distribution3.html

Sunday, January 5, 2014

Stupid IDN Tricks: Unicode Combining Characters (or http://░͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇.ws)

Nov 3, 2014: The domains mentioned in this article are expiring and I'm not renewing them. All links have been redirected to the archive.org mirror of the original site.



Safari will display Unicode combining diacritical marks in the URL bar (try going to  http://░͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇.ws). It is possible to register domains with these marks. Some of these domains will look much like legitimate domains (e.g. apple.com vs. apple͢.com). This is probably not good.

Internationalized Domain Names (IDN)


DNS was only designed with 7-bit unsigned ASCII in mind. However, not everyone in the world speaks English, and they really want to type domains in their own language. So there is a terrible hack to map Unicode characters to 7-bit unsigned ASCII, called IDNA.

Homograph Attacks


Hopefully everyone has heard of homograph attacks using internationalized domain names. If not, here is a recap (taken from the Chrome wiki):
... different characters from different languages can look very similar, and this can make phishing attacks possible. For example, the Latin "a" looks a lot like the Cyrillic "а", so someone could register http://ebаy.com (http://xn--eby-7cd.com/), which would easily be mistaken for http://ebay.com. This is called a homograph attack.

Defenses Against Homograph Attacks


There are multilayered solutions to the homograph attack:
  • Browser characters blacklists. These prevent you from registering characters that look like '/', and so on.
  • IDN character display rules (see: Firefox, Chrome). These rules restrict non-ASCII domain names to only those languages specifically configured by the user, and prevent display of mixed-language domains. For instance, if your have a Chinese installation of Windows then Chinese characters will be displayed for Chinese IDNs.
  • Registrar restrictions. Registrars will prevent you from registering a domain that combines  more than one language. So you can't register a name that is half English and half Russian, for instance.

Another Attempt


So how do we explain http://░͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇͇.ws?

Defeating Registrar Restrictions


Registrars prohibit combining languages in domain names. But there are characters that aren't in any language. The most interesting of these are Unicode Combining Diacritical Marks. These unicode code points will modify the glyph right before them, instead of adding a new character. For example, the letter A when combined with U+0x332 will become: A̲.

But will these characters display in browsers?

Chrome: No :(
Firefox: No :(
Safari: Yes :)

Impact


Someone could register apple͢.com and it would display in Safari as:

This is not good.