Web developer, open source enthusiast, amateur photographer & Linux user. Blogs @ http://t.co/Xgj1dYR9wb (en) & http://t.co/m0VDEYHnHq (fi)
39 stories
·
1 follower

Paying customers, not paying Facebook, Google, or Twitter.

1 Share

Our new Basecamp Referral Program splits $100 between existing customers and new customers rather than putting it in the pocket of those that track your every move online.

Last year we experimented with running ads on Facebook, Google, and Twitter. All-in we spent 6 figures on the experiment. And then we stopped.

But what stopped us wasn’t the spend, it was the feel. Every dollar you spend is a vote, and we were casting hundreds of thousands of votes for big companies that are tracking people’s every step, every move, every curiosity, and every detail of their lives. Fuck that.

Yeah, they could bring us customers. But we don’t like the way they do it. We don’t want to be complicit in the how. No thank you, no vote.

So, armed with the dollars and the drive, how do we introduce Basecamp 3 to more people? Who can we vote for to help us do this? The answer became clear: Our customers.

Why give money to Facebook, Google, and Twitter when we can give it right back to our customers? They’re better advocates for Basecamp than any ad we can write. They’re not a platform, they’re people who know other people who can surely benefit from Basecamp just like they are.

We want to cast millions of votes with our customers. We want to pay customers for customers. So that’s what we’re going to do.

Introducing the Basecamp 3 Referrer Program.

It’s simple. Refer someone to Basecamp, and we’ll PayPal you $50 cash. And that person you referred will save $50 on their first month. We’re basically splitting $100 — half to you to say thanks for sending someone our way, and half to them to say welcome aboard!

You don’t need to apply to be part of the referral program. All you need is a Basecamp 3 login. If you’ve got one of those, you’re already on board.

Just log into your Basecamp 3 account and look in the bottom right corner of your Home screen. You’ll see something like this:

Click it. Then you’ll see something like this:

Send your link to anyone you want. Or click one of the social sharing buttons below to spread the word on your social networks.

If someone signs up, pays, and remains a customer for at least 75 days, we’ll PayPal you $50. Easy peasy.

Designed differently

We used to have a referrer/affiliate program way back when, but it was complicated, you had to apply to be part of it, etc. We didn’t want to do it that way again. And many referrer programs pay you in credit towards the product you’re using. Problem with that is that if you’re on someone else’s Basecamp account, then your referral would give them credit. You wouldn’t see any of that cash. Not good either.

So we designed this program to pay cash to the person who referred, not credit to the account they’re part of. Now everyone can make a little something when they tell other people about Basecamp.

One for One

Ideally, we’d love to see every customer we have bring us just one more customer a year. That would be an amazing outcome.

Everyone’s gotta know at least one person who’s struggling at another small business with messy email chains, out of date files, stuff slipping through the cracks, constant hold-ups waiting for other people to get you information, and work scattered all over the place. Someone you know is swamped, and the tools they’re using are partially to blame. Let’s help them!

Save yourself $50 and do some good

If you aren’t already a Basecamp 3 customer, but you’ve been considering it, now’s a great time to try. Use my referrer link and you’ll save $50 off your first month. And I’ll donate the $50 that I’d be getting to the Chicago Food Depository.


Paying customers, not paying Facebook, Google, or Twitter. was originally published in Signal v. Noise on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read the whole story
iiska
41 days ago
reply
Oulu, Finland
Share this story
Delete

Machine Learning

5 Comments and 15 Shares
The pile gets soaked with data and starts to get mushy over time, so it's technically recurrent.
Read the whole story
iiska
42 days ago
reply
Oulu, Finland
Share this story
Delete
5 public comments
tante
42 days ago
reply
Actual illustration of how current machine learning (and AI systems) work
Oldenburg/Germany
growler
42 days ago
reply
Всё так
jimwise
42 days ago
reply
Lol
francisga
43 days ago
reply
This is actually exactly how Machine Learning works...
Lafayette, LA, USA
alt_text_bot
43 days ago
reply
The pile gets soaked with data and starts to get mushy over time, so it's technically recurrent.

Rental Car

2 Comments and 15 Shares
Technically, both cars are haunted, but the murder ghosts can't stand listening to the broken GPS for more than a few minutes.
Read the whole story
iiska
44 days ago
reply
Oulu, Finland
Share this story
Delete
2 public comments
fxer
43 days ago
reply
reticulating splines
Bend, Oregon
alt_text_bot
45 days ago
reply
Technically, both cars are haunted, but the murder ghosts can't stand listening to the broken GPS for more than a few minutes.

Drip campaigns — How we do them differently at Highrise

1 Share

I’m not a fan of most email I get. So I read very little of it :)

The worse offender is often drip campaigns from companies trying to keep me engaged with their product or service. You know the kind. You signup and then get a series of 6 emails someone wrote years ago that just keep coming to you.

They have some importance, right? There are things where you need some time to digest about the experience of working with a new tool or service that you don’t want to to be overloaded with immediately. You need to signup, get your bearings, learn the mobile app, learn how to do X. It just doesn’t make sense to clobber you over the head with all this at once. So some dripped education over the course of weeks or months is actually helpful.

The biggest problem with drip campaigns is they just feel robotic. There’s no human behind them even though they are often signed by the name of a founder or customer service person trying to “interact” with you. But you can tell. It’s robots all the way down.

So we’ve tried doing these a bit differently here at Highrise.

Change the Templates Every Day

This is the most important part of what we do. You can do this with most bulk email/drip campaign tools, but we use Highrise’s bulk email service to send out the majority of our mail to customers.

Just change the templates. Every. Day.

For example, I have a template that kicks off a series of email. It brings up a few different important aspects of getting started.

There’s a block early on:

That’s all about my day or weekend or family. This block was originally written a year ago, but this is what I delete and rewrite every single day. It takes minutes, often less than one, to mention something current and fresh.

Send replies to the highest priority queue

One of the worst mistakes people make with drip campaigns and other bulk mail efforts is that the replies go nowhere. The sender is “no-reply@wedontcare.com” or if it is a legitimate sender email, no one writes back.

It shouldn’t be this way.

All the drip/bulk mail I send is from my Highrise email address. Replies go directly to me. Often they are “thank you’s” and observations around the personalization of the email in the first place — see above if you skipped it :).

If I need help answering, I just forward them to the Support team at Highrise.

Now you might ask, “But Nate, your email inbox is a mess. 67k unread messages!? How can you reply to Highrise customers?”

Again, this is tool specific, but since I use Highrise, I use our auto-forwarding system and group inbox. I auto-forward my email to Highrise and have it whitelist just Highrise customers. That, combined with our group inbox, gives me a clean, prioritized inbox in Highrise that I keep empty.

But the big takeaway from this is you should use whatever tool gives you the workflow of making it a priority to handle replies to your drip campaigns or other bulk email.

Ask People to Chat

Most drip campaign email feels an awful lot like a lecture. “Here, you should try this.” “Hey again, you should do this.” “It’s been a few weeks, do this other thing.”

So I make sure to open up my email with a question:

Is there anything I can do?

I want to start a conversation here, not a lecture.

Give Them an Out

Emails are of course helpful, but sometimes it achieves the opposite effect.

You write your email trying to guide people through a ton of things they could possibly explore, but email is so direct. It’s not like the manual that comes with your car that you never bothered to read. A new email from you is probably at the top of their inbox. And then another comes.

Give people an out to realize this isn’t mandatory if it’s not helping.

I tell folks:

Also, Highrise is one of those products you can just use even if you lost the manual. But if you need any guidance there’s some resources below.

In other words, “Stop reading and throw this out, if this isn’t for you.”

Just Do It For Them

A lot of products have some kind of setup step. Maybe it’s an import of data. Maybe it’s setting up departments and filling out information for their users.

I’m always surprised more companies don’t just offer to do this for their customers. Your company’s employees, especially the support team, is faster at doing these steps than anyone, and once you get people past these things they are way more likely to stick with you than if they get stuck in setup.

So in our Welcome email we let new folks know:

Here’s some online help for doing an import with Highrise. Or if you’d like some help from us, reply to this email. If you have a spreadsheet of contacts, please attach the spreadsheet in your reply, and we’d be happy to help take care of that for you.

Of course you have to balance this with the size of the support team you have available. But in our case this saves more time than draining it because we don’t have to spend the extra time helping revert a bad import and redoing it if it didn’t work right the first time.

Those are just a few things we try and do differently. Some new things we’re fooling with are actually a customized email for each and every single person.

Alison here at Highrise created this effort and has shown us how awesome it is to send individual video emails to each customer (we use Bonjorno).

It requires the extra time, so it’s a balance to fit it in. But you can get an amazing amount of these out to customers with less effort than most people probably anticipate. It’s worth trying and adjusting if it isn’t scalable for your leads.

P.S. Please help spread this article by clicking the ❤ below.

You should follow my YouTube channel, where I share more about how history, psychology, and science can help us come up with better ideas and start businesses. And if you need a simple system to track leads, manage follow-ups, and send bulk email you should try Highrise.


Drip campaigns — How we do them differently at Highrise was originally published in Signal v. Noise on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read the whole story
iiska
52 days ago
reply
Oulu, Finland
Share this story
Delete

Combining fonts

1 Share
&&&&

I love the font Just Another Hand, I use it a lot in diagrams during my talks:

Here it is! Yay!

The thing is, I don't like the positioning of the hyphen & equals glyphs…

Cache-Control: max-age=3600

They look awkwardly positioned – they sit too high.

Thankfully CSS lets you merge fonts together, so I can create a single font family that's like Just Another Hand, except it takes the hyphen & equals glyphs from a different font, Architects Daughter:

Cache-Control: max-age=3600

How it works

The @font-face is defined as usual:

@font-face {
  font-family: 'Just Another Hand Fixed';
  font-style: normal;
  font-weight: 400;
  src: local('Just Another Hand'), local('JustAnotherHand-Regular'),
       url('https://fonts.gstatic.com/…woff2') format('woff2'),
       url('https://fonts.gstatic.com/…woff') format('woff');
}

But I added another @font-face of the same name for the hyphen & equals glyphs:

@font-face {
  font-family: 'Just Another Hand Fixed';
  src: local('Architects Daughter'), local('ArchitectsDaughter'),
       url('https://fonts.gstatic.com/l/…') format('woff2'),
       url('https://fonts.gstatic.com/l/…') format('woff');
  unicode-range: U+2d, U+3d;
}

The trick is in the unicode-range descriptor. It indicates that the src should only be used for the hyphen (U+2d) and equals (U+3d) code points. You can turn a unicode character into a code point using this snippet:

'='.codePointAt(0).toString(16); // "3d"

As an optimisation, I used Google fonts' text parameter to subset the "Architects Daughter" font, so it only contains the hyphen & equals glyphs. The woff2 version is 500 bytes – not bad!

And that's it. Now when I use:

.whatever {
  font-family: 'Just Another Hand Fixed';
}

…it uses a combination of both fonts!

Read the whole story
iiska
57 days ago
reply
Oulu, Finland
Share this story
Delete

HTTP/2 Server Push

2 Shares

Introduction

HTTP/2 is designed to address many of the failings of HTTP/1.x. Modern web pages use many resources: HTML, stylesheets, scripts, images, and so on. In HTTP/1.x, each of these resources must be requested explicitly. This can be a slow process. The browser starts by fetching the HTML, then learns of more resources incrementally as it parses and evaluates the page. Since the server must wait for the browser to make each request, the network is often idle and underutilized.

To improve latency, HTTP/2 introduced server push, which allows the server to push resources to the browser before they are explicitly requested. A server often knows many of the additional resources a page will need and can start pushing those resources as it responds to the initial request. This allows the server to fully utilize an otherwise idle network and improve page load times.

At the protocol level, HTTP/2 server push is driven by PUSH_PROMISE frames. A PUSH_PROMISE describes a request that the server predicts the browser will make in the near future. As soon as the browser receives a PUSH_PROMISE, it knows that the server will deliver the resource. If the browser later discovers that it needs this resource, it will wait for the push to complete rather than sending a new request. This reduces the time the browser spends waiting on the network.

Server Push in net/http

Go 1.8 introduced support for pushing responses from an http.Server. This feature is available if the running server is an HTTP/2 server and the incoming connection uses HTTP/2. In any HTTP handler, you can assert if the http.ResponseWriter supports server push by checking if it implements the new http.Pusher interface.

For example, if the server knows that app.js will be required to render the page, the handler can initiate a push if http.Pusher is available:

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if pusher, ok := w.(http.Pusher); ok {
            // Push is supported.
            if err := pusher.Push("/app.js", nil); err != nil {
                log.Printf("Failed to push: %v", err)
            }
        }
        // ...
    })

The Push call creates a synthetic request for /app.js, synthesizes that request into a PUSH_PROMISE frame, then forwards the synthetic request to the server's request handler, which will generate the pushed response. The second argument to Push specifies additional headers to include in the PUSH_PROMISE. For example, if the response to /app.js varies on Accept-Encoding, then the PUSH_PROMISE should include an Accept-Encoding value:

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if pusher, ok := w.(http.Pusher); ok {
            // Push is supported.
            options := &http.PushOptions{
                Header: http.Header{
                    "Accept-Encoding": r.Header["Accept-Encoding"],
                },
            }
            if err := pusher.Push("/app.js", options); err != nil {
                log.Printf("Failed to push: %v", err)
            }
        }
        // ...
    })

A fully working example is available at:

$ go get golang.org/x/blog/content/h2push/server

If you run the server and load https://localhost:8080, your browser's developer tools should show that app.js and style.css were pushed by the server.

Start Your Pushes Before You Respond

It's a good idea to call the Push method before sending any bytes of the response. Otherwise it is possible to accidentally generate duplicate responses. For example, suppose you write part of an HTML response:

<html>
<head>
    <link rel="stylesheet" href="a.css">...

Then you call Push("a.css", nil). The browser may parse this fragment of HTML before it receives your PUSH_PROMISE, in which case the browser will send a request for a.css in addition to receiving your PUSH_PROMISE. Now the server will generate two responses for a.css. Calling Push before writing the response avoids this possibility entirely.

When To Use Server Push

Consider using server push any time your network link is idle. Just finished sending the HTML for your web app? Don't waste time waiting, start pushing the resources your client will need. Are you inlining resources into your HTML file to reduce latency? Instead of inlining, try pushing. Redirects are another good time to use push because there is almost always a wasted round trip while the client follows the redirect. There are many possible scenarios for using push -- we are only getting started.

We would be remiss if we did not mention a few caveats. First, you can only push resources your server is authoritative for -- this means you cannot push resources that are hosted on third-party servers or CDNs. Second, don't push resources unless you are confident they are actually needed by the client, otherwise your push wastes bandwidth. A corollary is to avoid pushing resources when it's likely that the client already has those resources cached. Third, the naive approach of pushing all resources on your page often makes performance worse. When in doubt, measure.

The following links make for good supplemental reading:

Conclusion

With Go 1.8, the standard library provides out-of-the-box support for HTTP/2 Server Push, giving you more flexibility to optimize your web applications.

Go to our HTTP/2 Server Push demo page to see it in action.

Read the whole story
iiska
81 days ago
reply
Oulu, Finland
Share this story
Delete
Next Page of Stories