Category Archives: Software Business

Ad Attribution comes to iOS apps and the App Store

I have not heard a lot of hoopla about this, but I think this is a big deal. Back in 2019, WebKit announced a way to do ad attribution without per-user tracking. I put support for this in the AppStore on my WWDC 2019 wishlist.

The WebKit team just announced a privacy preserving ad attribution system for websites. I want the same thing to work for an ad for an app that appears on the web, App Store, or in another App. No need to attribute to a user — just the ad source is sufficient.

I explained in a followup:

The last few years have been a cat-and-mouse game between Ad Tech firms finding loopholes in iOS (e.g. shared Pasteboards) and Apple closing them. It would be much better if Apple provided a privacy preserving mechanism and then explicitly forbade anything else in the developer agreement.

I put this on my 2021 wishlist as well.

I just noticed this video on the WWDC Site: Meet privacy-preserving ad attribution, which appears to have done just that.

I don’t personally need this feature, but we need to do something to help out app developers who are under pressure to get some kind of ad effectiveness data. With IDFA basically gone, Ad Tech firms are going to resort to fabricating their own ID from whatever identifying information they can grab.

One thing to remember is that none of these firms have any kind of relationship with Apple. They are not parties to the developer agreement, so they have no obligation to follow it. It’s the developers that integrate their SDKs that take the risk and are the ones violating the agreement.

Another risk is that these SDKs inherit all of the permissions their host app has obtained. So, you could ask for location for a very good reason (e.g. you show the weather) and they could see that they have the permission and use it for something else (e.g. enriching their ad targeting database). Again, your app probably didn’t disclose this, but those SDKs don’t need to follow the rules—only you do.

So, I’m looking forward to this ad attribution method being adopted widely and for app integration to be done by the app developer just making HTTPS calls, not integrating an SDK. It may be too much to hope for, but it did require Apple to take the first step and offer a mechanism, which they now have.

Design by Comparing Opposites

In my podcast episode, Write While True Episode 7: Find Your Voice, I tried to express an idea that I find is useful in a lot of contexts. There are some choices where you are trying to make something specific or differentiating—in those cases, one way to know that you’ve done it is to see if the opposite choice is also reasonable.

In this case, I was talking about trying to find my “voice” in the podcast—what makes it mine and not generic. I recommended Joanna Wiebe’s video on voice and tone.

But, I cautioned against a voice that was “smart”. I said:

I actually don’t think smart is a good choice because the opposite of smart is very rarely appropriate. Everyone would choose to sound smart.

When you have a generically positive aspect that you want (like smart), a useful technique is to consider opposing ways to achieve it.

I recommended considering the choices of “expert” or “fellow learner” instead of smart. Both voices might be smart, but they are specific, opposite, and both are reasonable.

This is also a good technique in job seeking. It’s easier to find what you want if it’s not something that everyone would claim to have.

Sending a clear signal that “this is not for you” is the only way the people that it is for will recognize it.

Waiting to Promote Until You Are Sure is Wage-Theft

If you wait to promote people who are “already doing the job”, I think you’ll find that you don’t retain your best people. And if you are hiring people into senior positions instead of promoting, you don’t deserve to.

Even if you do, it’s a kind of wage-theft to not pay people for the work they are doing. A few months is ok, a year is absolutely not if you have the positions. If you’ve already done this, consider a bonus at promotion time.

If you have the positions, but people don’t seem ready, that’s on you. You should have supported and developed them before they were needed. If the opportunity is there, you should take the chance and responsibility for their success.

Meaning, if it doesn’t work out, you were the failure. You failed to develop them in time, and you failed to support them so that they were successful.

Applying The ONE Thing

I recently read The One Thing by Keller and Papasan. I recommend it, but the current VP of The ONE Thing was on an episode of Afford Anything, and it’s a very good introduction to the concept, if you want something quicker to digest.

The crux is that the authors ask you to focus on one question:

What’s the ONE Thing you can do such that by doing it everything else will be easier or unnecessary?

In a “five-why” fashion, you could start with your big goals and work backwards until you have the very first thing you need to do. They recommend dedicating a huge chunk of your time to that one thing, accomplishing it, and then moving on to the next ONE thing … ONE thing at a time.

For example, you might start with a goal to “Lose 10 pounds”, but end up with a ONE Thing like — learn how to cook five healthy, low calorie density, one-pot, bulk meals.

Don’t stop there, though. They want you to keep going—what is the one thing that would make that easier? Maybe you can find a local chef to come to your house and make them with you for the first three weeks. Perhaps you can get four friends to each learn one and teach the others (or swap freezer bags each week).

When I finished the book, I thought that my current ONE thing was to build up the number of tutorials on App-o-Mat, so I have been doing that. The eventual goal with App-o-Mat is to sell some kind of product there, but before that I need an audience, and you can’t get an audience unless you have useful content.

But, I am supposed to keep digging.

What is the The ONE Thing I could do to make making tutorials on App-o-Mat easier. One thing that has helped is having Sprint-o-Mat, because I just take code out of it as a basis for the tutorial. If I didn’t have that, making the app might be important.

But, if I break it down to something like this: I want 100 more articles on App-o-Mat by the end of July, then I see that I can only write about 25 of them at my current pace. What would make that easier?

Obviously, more writers. But 75 articles would cost about $15,000. So, is the real next ONE thing to get $15,000 of revenue? Or at least $5,000 in May?

I’m still working through this. If App-o-Mat were a serious business, investing $15,000 would be a no-brainer, but honestly, it’s not. Right now, I want to have the experience of writing, and I don’t want to manage and edit a bunch of writers.

But, I do think that a trickle of articles by others would be ok, so I will explore that. I also think that if I doubled-down on the time I spend writing articles, I could do a lot more, which means dropping some other things or just getting more disciplined.

Keller would say to break down “getting more disciplined” first because he’s kind of annoying that way.

So, to do that, I am going to make my One thing to come up with article series ideas that could each have many articles in them. Because then, I’d at least have a checklist I could work from and could put them on a schedule. I think I’d see the possibility of outsourcing better as well.

Tech Debt Happens to You

In the original ANSI C as described by K&R, there are a bunch of library functions that use internal state static variables. An example is strtok, which you call with a string to tokenize, and when you want the next token, you call it with NULL. strtok uses internal static variables to keep track of the string and an iterator in it.

In early C usage, this was fine. You had to hope that any 3rd party library call you made while iterating tokens weren’t also using strtok.

But, then when threads were introduced to UNIX and C, this broke down fast. Now, your algorithms couldn’t live in background threads if they used strtok. This specific problem was solved with thread-local variables, but the pervasive use of global state inside of C-functions was a constant source of issues in the most multi-threading and post multi-processor world.

And the world was changing from delivering desktop apps to web apps, so now a lot of your code lived in a multi-threaded back-end that serviced simultaneous requests. This was a problem because in early web development, we took C-libraries out of our desktop apps and made them work in CGI executables or NSAPI/ISAPI web-server extensions (similar to Apache mod_ extensions)

To make this work, we had to use third-party memory allocation libraries because the standard malloc/free/new/delete implementations slowed down as you added more processors (from constant lock contention). Standard reference-counting implementations used normal ++ and -- which aren’t thread-safe, and so we needed to buy a source code implementation of stl that we could alter to use InterlockedIncrement/InterlockedDecrement (which are atomic, lock-free, and thread-safe).

As the world changed around us, we could keep moving forward with these tech-debt payments.

Also, this was slow-paced problem—strtok/malloc/etc were written in the 70s and limped through the 90s. That’s actually not that bad.

But, the world doesn’t stop. Pretty soon, it was just too weird to implement back-ends as ISAPI extensions. So, you pick Java/SOAP because CORBA is just nuts, and well, that’s wrong because REST deprecates that, and then GraphQL deprecates that, and you picked Java, but were you supposed to wait for node/npm? Never mind what’s going on on the front-end as JS and CSS frameworks replace each other every 6 months. Even if you are happy with your choice, are you keeping your dependencies up to date, even through the major revisions that don’t follow Substitutable Versioning?

And I think that this is the main source of tech debt, not intentional debt that you take on or the debt you accumulate from cutting corners due to time constraints. The debt that comes with dependency and environment changes.

Being able to bring code into your project or build on a framework is probably the only thing that makes modern programming possible, but like mortgages, they come with constant interest payments and a looming balloon payment at some point.

There are some you can’t avoid, like the OS, language, and probably database, but as you go down the dependency list, remember to factor in the debt they inevitably bring with them.

Mitigating the Mitigations

The first step to dealing with project risk is to list mitigations—the steps you will take to avoid or handle the risk. But, don’t stop at just listing them.

The very next step should be to think about whether those mitigations themselves have obstacles.

For example, let’s say you have a project with a large mechanical portion, which doesn’t require communication or coordination to implement. If this work can be done in parallel, then adding engineers mid-way (once the a core has been established) could speed up the project, but even at the start, you must

  • Get budget approval
  • Find a source of engineers (contractors/internal)
  • Structure the work so that at some point it can be done without coordination and in parallel.

Projects like converting a lot of code from Objective-C to Swift or from an unsupported version of a framework to the current one work well for this. Projects that require a lot of cross-developer coordination are famously made later by adding engineers.

Depending on the stakes, it might be right to ask engineers to temporarily put in more hours, or to schedule time-off earlier in the project if possible. These things are easier to do if you talk about them earlier and gauge the impact.

A third option would be to clear off all other work so that everyone can concentrate on the high-priority work at hand. In that case, those projects have risks that need to be communicated to the project managers so that they can list and mitigate them.

It would be frustrating for a project risk to manifest itself, to have identified that early, and to have come up with an effective mitigation, which is not possible to do because it needed prior planning.

Software that knows ROI

Businesses adopt software for some rational reason. That reason is often expressed as a return on investment (ROI).

Based on the home pages of most software vendors, sales and marketing definitely know this. But based on the actual software, product development doesn’t seem to. Good software delivers ROI, but most don’t bother to tell you afterwards.

Decision makers in the organization care about this metric and will try to predict it before adoption and will probably track it afterwards.

And even if they don’t—if they were to magically know this metric, it would inform their decisions about renewal and increasing adoption. Sales and marketing lead with this info because they know that it’s a compelling selling strategy. They use ROI language in case-studies and may even have an ROI calculator on their site.

What I don’t see as often is an ROI calculator right in the software itself.

This is a huge missed opportunity. Lots of software has the exact data on how well it has achieved an ROI for you. That number is also a proxy for the ROI of the user that operates it or the decision maker that purchased it, so they would be very likely to want to share it.

SaaS products have a bigger advantage of not only knowing the ROI, but also being able to compare across customers and derive insights to why some customers are getting more benefit than others.

This information can drive account management calls, webinar topics, training, etc. Not to mention that the software could try to drive the user to those behaviors.

The model here to look at is Google Adwords. ROI literally drives the entire product UX and is reported on a line-item basis. It is deeply integrated into how you think of the product and adword metrics, PPC and CPC, have become common vocabulary in the industry.

So, what about your software? What is driving its value? Is that information readily available in the product itself? Does it drive user behavior? If not, how could it? Contact me if you want to talk more about this.

Tech Career Tip: Drive Revenue, Not Cost

I have spent most of my career in software product development, meaning the code I wrote went into the products that made money for the company I worked for. I did a short stint writing internal software for the organization itself and the difference was very stark to me.

When you write software for your organization, it’s often to automate something and the driver is cost-reduction. The problem is that cost can only be reduced so much and eventually you are one of the biggest costs (in a budget owned by someone who likes to cut).

Revenue, on the other hand, can be very outsized compared to your cost. The budgets for product development are often expressed as a percent of revenue, so success increases budgets.

And, often, product development jobs offer some way to participate in that upside (options, RSUs, etc). Getting equity from an IT developer isn’t as easy.

It’s more complex than just “for-sale” or “internal”. When I was in FinTech, I wrote products, but my peers at banks, writing internal software, certainly drove revenue for their employers and were paid very well through generous bonus systems.

Pay is not the most important benefit. When you are critical to how a company makes money, you have bigger growth opportunities, more respect, and generally more clout. Product developers at software product companies have career prospects that lead all the way to CEO. That is not often the case for developers automating internal operations.

Proposal Tip: Offer Choices

Most of my consulting proposals have options in them. I generally think that customers like having a choice in how to proceed, and it gives me a chance to express different ways I could help.

It’s hard not to have a preference for what they might pick. For example, you might want them to pick the most expensive option. I don’t always want that—sometimes an option is expensive because I don’t want to do it.

But, I find it best if I am neutral to their choice. I don’t want to be disappointed if my preferred option isn’t chosen.

In contrast, I want the customer to have a clear best choice. I don’t want them agonizing over the options, so they are usually pretty different. I might not know exactly which one they want, but it won’t be a close call.

For example, in an app proposal, one option might be to build the app. I don’t offer different ways I could do that, but I might offer to only be a project manager for an offshore team instead. Two very different options.

Each option is acceptable to me, but I think the customer would find choosing one easy.

In Your Personal Network, Be the Server

If you want to “network”, don’t think of it as trying to meet people, or trying to find customers. Think mostly of servicing the network you already have

Consider everyone already in your network to be your clients. This doesn’t mean “customers that pay”, it means “clients that you serve”. It means you care about their well-being. You would help them if asked. You are interested in them and their problems.

There are times when they make requests, and you would do it freely—do it and follow-up. There are times when servicing the request should cost money—make that clear.

But, the important thing here is actually care about them and their problems, not yourself and your problems.

Make deposits. Do this constantly. Do it right now. Just build up as much good-will as you can. Also, to be clear here: likes, shares, and engagement on social posts are not deposits.

What if you actually need something from someone?

Ok, at some point, you might a withdrawal. Paid work, a recommendation, an introduction. Some of those are small enough, just ask. Let them know what happened—follow-up.

For bigger asks, to the extent that it is possible, figure out how your withdrawal might also be a deposit. For example, can you ask your paid clients how you can deliver more value to them? How you can help their contacts?

If your mindset is to serve, you will constantly come up with ideas.