August 2022 Retro

I turned 30.

In August I bumped my head on a few front-end issues and finally realised that I’m building a type of web analytics service (think Simple Analytics , Plausible Analytics , Splitbee , etc.).

Last month’s goals

  • Get my Facebook app approved & published.

    Result: I got approved, but I haven’t published the Facebook app yet.

    Grade: B

  • Get my Shopify app approved & published.

    Result: I haven’t submitted my Shopify app for review.

    Grade: F

  • Tweak AdSlicer to track more sales than Facebook.

    Result: My results have improved, but still lagging behind Facebook.

    Grade: C

  • Turn 30.

    Result: I nailed it!

    Grade: A+

Main events

Facebook hoops

My Facebook app submission got approved, but I haven’t published it yet. The FB dev experience is reasonably good, so an unpublished app isn’t limiting my live testing.

One less thing to worry about before launching (again) publicly.

Not so fast, cowboy! As I’m writing this I get this FB notification:

Some additional requirement Facebook just made up. Some additional requirement Facebook just made up.

Another hoop to jump through.

Front-end woes

So far AdSlicer is the most complex single page app I’ve built. It’s a classic React SPA talking to a Django API.

Django is my bread & butter, but I still feel so noob with React. Oftentimes, I’d code myself into a corner, specifically around state management. For example, on any given page, I would need to conditionally render content based on multiple pieces of data that is asynchronously retrieved from the API. It becomes a headache to consider the state that each dataset might be in (i.e., initial, loading, complete). Was building an SPA a mistake?

I eventually dig myself out of these holes and learn something along the way. But falling into these gotcha’s is a huge time-suck and an overall distraction from building the actual product.

It’s times like these that I value boring advice like “Stick to what you know”. I don’t know how to sell software. Now I don’t know how to build it either.

I now understand the advice as “Flatten the (learning) curve to avoid reaching a point of giving up”.

Mismatching results

AdSlicer’s main value proposition is that it can attribute more ecommerce sales to your (Facebook) ad efforts.

This isn’t true, yet.

The problem (and opportunity) lies in how Facebook attributes sales back to ads. Currently, Facebook uses a 7-day click & 1-day view attribution window. This means:

  1. If someone clicks on an ad and, within 7-days, makes a purchase then that sale is attributed to that clicked ad.
  2. If someone views an ad and, within 1-day, makes a purchase then that sale is attributed to that viewed ad.

I can improve on #1 because clicks direct user’s off of Facebook where I can gather my own data and increase the 7-day limit to, say, 30-days instead.

I can’t improve #2 because views happen on-Facebook and I have no way of telling if a website visitor viewed (but didn’t click) an ad.

In short, AdSlicer is limited to only click attribution while Facebook has both click & view attribution. This isn’t a show stopper, but it is important for comparing apples to apples.

Up until now, I’ve been comparing apples to oranges.

Limited live data

I have AdSlicer’s tracking script running on two live ecommerce stores, collecting data (i.e., page views, purchases, etc.).

Unfortunately, moments after publishing my last retro, both store owners decided to pause their ads until spring (i.e., 1st September). So I didn’t have much data to benchmark & tweak.

I did however, make some minor improvements to my server’s reliability which got me thinking about AdSlicer’s overall availability . And currently it’s not great.

Another way of improving my results is to ensure that I actually capture the data to begin with. Missing even one purchase event diminishes AdSlicer’s value.

Oof! I, a solo founder, am building a SaaS that requires high-availability 🤦‍♂️.

I’ve seen other solo founders, way more experienced than me, actively avoid building businesses that require high-availability. Basically, anything that would cause angry users to call them in the middle of the night.

Great advice, that I can finally appreciate.

The way I see it, there are two types of AdSlicer traffic:

  1. Machine-to-machine requests. These are valuable asynchronous tracking events that requires high-availability. These requests happen behind the scenes while people are browsing an ecommerce store.
  2. User-to-machine requests. These are the requests made by AdSlicer users via the React SPA. If a request fails or takes too long then it’s not a big deal. People will either complain, try again, or leave. But hopefully if AdSlicer is useful enough, none of that would matter.

So AdSlicer has a high-availability component which I think is manageable as a solo dev.

Time

This is closest I’ve come to working an average of 40 hours per week (since going solo). I (conceptually) value direction more than hard work, but being solo really screwed my sense of direction.

So the increase in hours worked might be because I have a better idea of what I’m building…

Or it might be because I doubled my coffee intake since receiving a 2-cup french press for my birthday.

A breakdown of how I spent my time last month (via Toggl). A breakdown of how I spent my time last month (via Toggl ).

This month’s goals

  1. Reduce the load time of AdSlicer’s tracking script.

    Details from the Chrome dev tools network tab when loading my tracking script. Details from the Chrome dev tools network tab when loading my tracking script.

    I’ll try use a CDN and minify the JS, but if you have any other ideas then please let me know 🙏.

  2. Reduce the latency of AdSlicer’s tracking events.

    Details from the Chrome dev tools network tab when sending tracking events to my server. Details from the Chrome dev tools network tab when sending tracking events to my server.

    I’ll try use a Lambda function that saves the event data into a queue and then add a 2nd Lambda function that saves the data to the DB.

  3. Tweak AdSlicer to track more sales than Facebook.

    This is going to be an ongoing effort that I’m not completely sure is possible. It’s pretty easy for Facebook (and AdSlicer competitors) to inflate stats based on super broad matching criteria. For example, matching a person’s browsing activity based on their cookies vs IP address vs browser fingerprint vs which hemisphere they’re in. The broader I go, the more sales I can attribute. I don’t want to do that, but I can’t stop others from doing that. So maybe AdSlicer’s value metric is wrong 🤔.


Thanks for making it this far. If you're interested in what happens next, I'll email it to you next month.