Tag: csa-pillar-story

  • We Finished Building the App. Then We Had to Prove It to a Stranger.

    We finished building the feature. We tested it. We were, frankly, a little proud of it. Then someone reminded us that “done” and “allowed to show this to actual merchants” are two very different states, and the gap between them is filled almost entirely with paperwork.

    Getting an app listed on the Shopify App Store isn’t a toggle you flip once the code works. It’s a real review process, and a meaningful chunk of it has nothing to do with whether your app actually functions — it’s about proving, to someone who has never used your product and has no reason to trust you yet, that it does what you say it does.

    What does it actually take to get an app listed on the Shopify App Store?

    For us, it meant two things that took longer than expected: a recorded walkthrough showing a reviewer exactly how the app is meant to be used, start to finish, and a written set of testing instructions explaining how to set up a test account and exercise every part of the thing we’d built. Neither of those is a line of code. Both of them took real time to get right, and both of them exist for the same reason — so a reviewer who has never seen your product before can verify it does what the listing claims, without having to take your word for it.

    That part surprised us a little. We’d budgeted time for building the feature. We hadn’t really budgeted time for explaining the feature to a stranger who was going to judge whether it was allowed to exist in front of real merchants.

    Why does a working app still need a video and a script?

    Because “it works” isn’t actually the question a reviewer is answering. The question is closer to: does this app do, reliably and exactly, what it tells a merchant it will do — and can someone outside the company that built it confirm that, on their own, without the builder standing over their shoulder explaining it away? A screen recording and a written path through the product are the two most reliable ways to make that answer checkable by someone else, instead of just asserted by us.

    It’s a slower process than we expected going in. It’s also, once you sit with it, a reasonable one. The alternative — an app store where listing is just “upload your code and go live” — is the version where a merchant has no real signal that anyone outside the app’s own team ever looked closely at it before it showed up asking for access to their store.

    Why this matters to you

    When you’re deciding whether to trust a new app with your store’s data, whether it’s listed on the Shopify App Store (rather than only available as a private link or a direct install) is a real, checkable signal — not a guarantee of quality, but evidence that someone other than the people who built it looked at a working walkthrough and a documented test path before it was allowed to go live. It’s worth noticing the difference between an app that’s genuinely listed and one that’s just linked to you directly, especially before you connect anything that touches customer data.

  • We Picked Our Price the Slow Way: By Actually Checking What Everyone Else Charges

    Picking a price for a brand-new product feels like it should take ten minutes and a gut feeling. We tried the gut-feeling method first. It lasted about ten minutes before we talked ourselves out of it.

    So we did the less exciting thing instead: before we wrote down our own number, we actually went and looked at what real competitors charge, one pricing page at a time, rather than trusting a secondhand roundup or a “competitors typically charge” line from a pricing consultant’s blog post.

    Why not just pick a round number?

    Because a round number picked from a gut feeling tends to mean one of two things later: you’re leaving money on the table, or you’re asking merchants to pay more than the market will bear for what you’re actually offering. Both are avoidable if you just go look. So we went and looked — at ten tools in our own category that a Shopify store owner would realistically be comparing us against.

    What we actually did

    We opened each tool’s live pricing page ourselves, not a comparison chart someone else put together, and wrote down what each one actually offered at each price point: what counted as the “free” tier (if there was one), what features were gated behind which plan, and where the real jump in price happened. It’s slower than reading a roundup. It’s also the only way to know you’re comparing what’s true today, not what was true when someone else last checked.

    What surprised us

    Going in, we expected most of these tools to offer some kind of real free tier, since that’s the industry’s default move. Only a minority actually did once we looked closely — several “free” options turned out to be time-limited trials dressed up as a free plan, or a free tier so limited it couldn’t realistically run a real store’s reporting.

    One honest caveat here: pricing pages change, sometimes without much notice. Anything specific we noticed during our own research is a snapshot of that day, not a permanent fact about any competitor. If you’re using this as a reason to check a specific tool’s current pricing before you rely on it for your own decision, that’s exactly the right instinct — go look at their live page the same way we did, not an older summary of it, ours included.

    Why this matters to you

    When you’re comparing analytics tools for your own store, don’t stop at the sticker price. Pull up each tool’s actual current pricing page yourself and check three things: whether the “free” tier is genuinely free and genuinely usable (not a disguised trial), which features are locked behind the plan above the one you’re looking at, and whether the price jump between tiers lines up with a real jump in what you get. That ten-minute check, done directly on the source instead of a comparison article, is the same homework we did before we set our own price — and it’s the fastest way to catch a tool that looks cheap until you actually need the feature that was never included.

  • We Built a Permanent Fake Customer. On Purpose. For a Very Boring Reason.

    Every piece of software ends up with at least one feature built entirely for an audience of one person who will never pay you anything. Ours doesn’t even have a name on the invite list. It’s just an account.

    Here’s the direct version: before yoursignalstack could go live on the Shopify App Store, a human reviewer at Shopify needed to actually see what our most expensive plan looks like — the real thing, every feature switched on, nothing held back for a demo. The catch is obvious once you say it out loud: that reviewer isn’t going to pull out a card and pay for our top tier just to check our work. So we built a permanent account, locked to the top tier, that exists for exactly one reason — letting someone see the real product without a single dollar changing hands.

    Why can’t a reviewer just use a free trial?

    A trial seems like the obvious answer, and it’s the first thing we considered. The problem is that a trial is built to behave like a trial — it runs on a clock, it’s meant to convert or expire, and depending on when a reviewer starts it, it might not even land on the exact plan that needs checking. App review isn’t a one-time glance either; a reviewer can come back to re-check something weeks later, after any reasonable trial window has closed. We needed something that would look identical no matter when someone showed up to look at it, which a time-limited trial can’t promise.

    So what did we actually build?

    Nothing clever, honestly — that’s half the point. It’s a standing internal account, permanently set to our top pricing tier, with no live billing attached to it at all. It doesn’t go through checkout, it doesn’t have a card on file, and it isn’t reachable by anyone outside the review process. It just sits there in the exact state our highest-paying real customer would be in, available whenever someone needs to confirm that what we say the top plan does is actually what the top plan does.

    It’s a small thing. It took more thought than you’d guess to get right, and it will never show up in a changelog or a feature announcement, because it isn’t a feature — it’s plumbing for a process our actual customers never see and don’t need to think about.

    Why this matters to you

    The honest takeaway isn’t really about us — it’s about how much of building software has nothing to do with the features you’ll ever click on. A real chunk of development time on any app goes to logistics like this: satisfying a platform’s internal process, proving something works to someone who will never be a customer, building one-off tooling that exists purely so a review can happen at all.

    Here’s the concrete version you can actually use: the next time you’re comparing apps on the Shopify App Store and a listing shows screenshots of a top-tier plan you haven’t paid for, that image usually isn’t a mockup. Somewhere behind it is very likely a setup like ours — a standing account built just so someone could show the real thing without routing it through live billing. It’s a small detail, but it means those top-tier screenshots are generally more trustworthy than you’d assume by default, precisely because somebody had to go out of their way to make that view possible in the first place.

  • The Bug That Looked Like Our Billing System Was Broken. It Was One Flag.

    Every product has one bug that ages the person who found it by about a year in the space of a single afternoon. This is ours. It never touched a single dollar of anyone’s money, but for a few hours it felt like watching the whole payment stack quietly catch fire.

    Here’s what actually happened: the Shopify Admin API started silently returning 403s for a subset of merchants. No error banner, no obvious pattern at first — just requests that should have worked, quietly failing. The eventual root cause was an access-token expiry edge case, and the fix that resolved it was passing a single parameter, expiring:1, on the relevant API calls.

    Why did a one-flag fix take real debugging to find?

    Because the symptom didn’t point at the cause. A 403 on an Admin API call looks like an authorization problem — a wrong scope, a revoked access, a permissions bug in our own code. It does not look like “this token is a specific kind of expiring token, and the request needs to say so explicitly.” We chased the obvious suspects first, because that’s what the error actually resembled. It took working backward from which merchants were affected, and what their tokens actually had in common, before the real shape of the problem showed up.

    What the fix actually was

    Once we found it, the change itself was small: pass expiring:1 so the API call correctly accounts for tokens that expire, instead of assuming the older, non-expiring token shape. It shipped as migration 0078. The real lesson wasn’t about the flag itself — it was how much debugging can hide behind a fix that, once found, looks embarrassingly simple.

    What we’d tell someone hitting the same thing

    If you’re integrating with an API that has more than one token type or auth flow, and you see 403s that don’t match the permissions you think you’ve granted, don’t assume the bug is where the error is pointing. Check whether the token itself is a different shape than the one your code was written against. That mismatch is invisible until you go looking for it specifically.

    We’re building yoursignalstack in public, bugs included, because we’d rather you see the real process than a highlight reel. If you want to follow along, leave your email and we’ll let you know when it’s live.

    Get notified when yoursignalstack launches →

  • We Checked Our Own Pricing Page Like a Customer Would. We Didn’t Love Everything We Found.

    There’s a particular flavor of discomfort in grading your own homework and realizing you wouldn’t pass it. We got a taste of that recently, except the homework was our own pricing page, and the person grading it was also us. Somebody had to do it honestly, so we did.

    Here’s the short version: we went through our product line by line and checked whether what we actually let a merchant do matches what our pricing page says they can do, depending on which plan they’re on. It mostly matched. Not entirely. We found a few places where the gap between the promise and the product had quietly opened up, and we closed it.

    What’s the difference between a pricing page and the product itself?

    Your pricing page is a promise written in marketing language: “Starter gets you X, Pro gets you X plus Y.” The product itself is a pile of code that has to actually check, every single time a feature loads, which plan the account in front of it is on, and decide whether to allow or block accordingly. Those are two separate things, written at two separate times, usually by different parts of a small team moving fast. They start out matched. Then the product changes — a feature gets reworked, a new one gets added, an old restriction gets refactored — and the pricing page doesn’t always get updated in lockstep. Nobody plans for that drift. It just happens, the same way a junk drawer fills up without anyone deciding to fill it.

    What did we actually find when we checked?

    We went through the pricing page claim by claim and tried to break it the way a skeptical customer would: log in on each tier, try the things that tier isn’t supposed to get, and see what actually happens. In a few spots, the code wasn’t checking as carefully as the pricing page implied it would. Nothing dramatic, nothing that cost anyone money or exposed anyone’s data — but real gaps between “here’s what you’re paying for” and “here’s what the software actually enforces.” We fixed what we found. It wasn’t a fun afternoon, but it was a necessary one.

    Why does this happen even when nobody’s trying to cut corners?

    Nobody sits down and decides to let a Starter-tier customer quietly use a Pro-tier feature. It happens in small steps: a feature gets rebuilt and the new version forgets to re-check the old restriction, or a feature gets added to one plan and someone assumes the gating will “obviously” carry over, or the pricing page gets reworded in a sales meeting and the engineering ticket to match it never gets filed. Every one of those is a small, forgivable, completely human miss. The only real defense is going back and actually checking, on a schedule, instead of assuming the page and the product are still telling the same story.

    Why this matters to you

    This isn’t just a story about us. It’s a habit worth borrowing for anything you pay for. The next time you’re on a free trial for an analytics tool, a marketing app, or anything else billed by plan tier, don’t just read the pricing page and take it on faith. Actually try the things your plan is supposed to include, and if you can see what a higher tier offers, try poking at those too. If something you shouldn’t have access to works anyway, or something you’re paying for doesn’t actually show up, that’s worth a support ticket, not a shrug. Pricing pages are promises. The only way to know a promise is being kept is to test it yourself, the same way we had to test ours.

  • Getting Permission to Read Your Google Analytics Took Longer Than Writing the Code

    Developers like to imagine the hard part of building something new is the code. We can report that, at least once this year, the hard part was a form.

    Here’s what happened: to show a merchant their own Google Analytics numbers inside yoursignalstack, we first needed Google’s permission to ask for that data at all — not permission from the merchant, who’s obviously free to connect whatever they like, but from Google itself, as the company deciding whether to trust us with it for anyone. Getting that permission meant going through Google’s own formal review process before a single real merchant (as opposed to our own test accounts) could connect their Google Analytics.

    Why does an app need Google’s permission just to show you your own data?

    Because the connection isn’t really just between you and the app. It’s a three-way relationship, and Google is the party in the middle deciding whether to hand your information to a given piece of software — not just for you, but as a blanket decision that applies to every merchant who might ever connect that app. Before Google will let an app ask a wide group of real users for that kind of access, it reviews the app first.

    That review isn’t a courtesy step. It’s the actual gate between “we built a feature that reads Google Analytics” and “a real store owner can click connect and have it work.” Until it clears, the feature can exist perfectly well in testing and still be unusable for anyone outside our own accounts.

    What does that review actually check?

    In plain terms: exactly what data is being requested, why the app needs it, and whether the request is as narrow as the stated purpose allows. An app asking to read your analytics numbers gets looked at differently than one asking to also edit your account settings or see unrelated data it has no real use for — the specific list of permissions involved (what the industry calls “scopes,” for anyone who stumbles on the term) has to match the app’s actual job, not just be requested broadly “in case it’s useful later.”

    The review also looks at how the data is handled once it’s in the app’s hands: whether there’s a real privacy policy, whether the stated use matches what the app is actually built to do, and whether the request is read-only or something broader. None of that is a formality you can rush through by filling out a form correctly — it takes real back-and-forth, and real time, before Google is satisfied enough to let an app ask ordinary users for that access.

    What should you take from this the next time an app asks to connect to your Google account?

    You’ve probably seen the screen this produces: the one that lists, in plain language, exactly what a piece of software is asking to see or do on your Google account, with an Allow button at the bottom. Most people click through it fast. It’s worth actually reading, for two reasons.

    First, that screen is a direct, unfiltered list of what the app will be able to touch — not marketing copy, not a summary, the actual permissions. If a tool that’s supposed to show you analytics numbers is asking for access to edit your ads or your site content, that’s worth pausing on. Second, if you ever see a warning that says Google hasn’t verified an app, that’s not a glitch — it means the app hasn’t (yet, or ever) gone through the review described above. That’s not automatically a reason to refuse it, especially for something small and early-stage, but it is a reason to look harder at who built it and what it’s actually asking for before you click through.

    Why this matters to you

    Next time any tool asks to connect to your Google Analytics, Google Ads, or similar account, actually read the permission screen before clicking Allow. Check whether it’s asking for read-only access to the specific thing it needs, or something broader than its stated purpose would explain. And if you see an “unverified app” warning, don’t treat it as background noise — it’s Google telling you this particular app hasn’t been through the review process we just went through, which is worth knowing before you decide whether that’s fine or not. It’s a small habit, it takes about ten extra seconds, and it’s the same check we’d want a merchant to run on us.

  • We Broke Our Own Success Message. Nothing Else Broke.

    Every so often a bug report lands sounding like the end of the world, and the actual fix turns out to be a lot smaller than the report. This is one of those — worth mentioning anyway, because the honest version of “building this” includes the small, slightly embarrassing bits, not just the wins.

    Here’s what happened: after someone finished creating a new login, the message confirming it worked didn’t look right. Nothing was actually broken in the sense that matters — no account was in danger, no data went anywhere it shouldn’t have. It just looked off, like a note stuck to the wrong cabinet.

    Was anything actually wrong?

    No. The account was created correctly, the login worked, and everything behind the scenes was exactly where it should be. The only thing wrong was the confirmation message itself — the on-screen note telling you “you’re all set” didn’t line up the way it was supposed to. We caught it, fixed the layout, and moved on.

    We’re mentioning it anyway because it’s a useful reminder of a distinction that’s easy to lose in the first few seconds of seeing something look wrong on a screen: a cosmetic problem and a real one are not the same animal, even though they can look identical at first glance.

    How do you tell the difference, as a store owner?

    You usually can’t tell just by looking, and you don’t need to diagnose it yourself. What you can do is check whether the thing you were actually trying to do happened: did the order go through, did the account get created, did the setting actually save. If the underlying action worked and only the on-screen confirmation looked strange, that’s a cosmetic bug, not a broken system.

    That distinction changes what you should do next. A cosmetic bug is worth reporting — any honest company wants to know their screen looks wrong — but it’s not a reason to panic, re-enter your information twice, or assume your data got corrupted. A bug where the actual action didn’t happen is the one that deserves urgency.

    Why this matters to you

    Next time something looks off in a tool you use — a confirmation message that seems misplaced, a button that looks slightly broken, a page that renders oddly for a second — don’t assume the worst by default. Check whether the actual action happened: did the order place, did the setting save, did the email actually send. If it did, you’re almost certainly looking at a small cosmetic bug — worth a quick report to the company so they can fix it, but not worth losing confidence in the tool over. We’d rather you tell us when something looks wrong than quietly assume everything underneath it is broken too. That’s true of us, and it’s a fair standard to hold any tool you pay for.

  • The Second Time You Connect an App Should Be Easier Than the First. For a While, Ours Wasn’t.

    Software teams pour an enormous amount of care into first impressions — the signup screen, the onboarding tour, the first dashboard a new user ever sees. Then, months later, something breaks that connection and you find out how much thought actually went into that moment. For us, the honest answer was: less than we’d like to admit.

    Here’s the short version. When a merchant’s connection to yoursignalstack needed to be reset and reconnected, the process we’d built for that moment was worse than the process we’d built for the very first signup. We found it, fixed it, and it’s a useful example of a blind spot that’s easy for any piece of software to have.

    Why does “reconnect” ever feel harder than “connect”?

    Think about where most of a product team’s design effort actually goes. It goes toward the first-time setup — because that’s the flow that gets demoed, tested by reviewers, shown off in screenshots, and walked through in onboarding emails. The second time anyone goes through a connection flow is usually because something broke: a password changed, a permission expired, a platform asked for re-approval. Nobody reconnects an app for fun. By definition, the person going through that flow is already having a worse day than a brand-new signup ever has.

    That’s roughly what happened on our end. Some merchants who needed to reauthorize their store login ran into a version of that flow that didn’t behave the way the first-time version did — instead of walking them cleanly back in, it stalled out partway through. (In plain terms: the path for logging back in after a disconnect wasn’t built with the same care as the path for logging in the first time.) We caught it, rebuilt that flow so reconnecting works as smoothly as connecting did originally, and shipped the fix.

    Why this matters to you

    If you’ve ever had to reconnect an app to your store — after a password reset, a permissions change, or Shopify asking you to re-approve something — and it felt clunkier or more confusing than the first time you set it up, that’s not just you having a bad day with the tool. It’s a genuinely common blind spot in how software gets built, precisely because the second-time flow gets far less attention and far less testing than the first.

    It’s worth actually testing yourself. Pick an app you rely on for your store, find its “reconnect” or “reauthorize” option, and click through it now — while nothing is actually broken — instead of discovering how it behaves for the first time during an actual outage, when you’re already stressed and your dashboard already looks wrong.

  • The Easy Fix Was One Line. We Built Something Slower Instead.

    Every roadmap has a moment where the fast, invisible fix is sitting right there, fully formed, ready to ship before lunch. We had one of those. We looked at it for a while, and then we didn’t ship it.

    Here’s the situation: yoursignalstack includes an AI assistant we call Jack, and every plan comes with a set amount of Jack usage built in. Eventually, some merchant was going to use up what came with their plan before their billing period reset. We had to decide what happens next.

    What happens when you use up what’s included with your plan?

    There are really only two honest answers to that question. Either you cut the merchant off until the next cycle, or you let them keep going and charge them for the extra. We wanted to do the second one — nobody likes hitting a wall on a tool they’re actively relying on.

    The fast version of that was easy to picture: just reset the usage counter back to zero on a timer, and let the overage math work itself out roughly. It would have taken an afternoon.

    Why we didn’t ship the fast version

    The problem wasn’t the idea. It was where the reset actually happened. Behind the scenes, not every merchant’s account runs through the exact same billing plumbing — different merchants, added at different points, ended up wired through more than one billing system. From the outside, that’s completely invisible. From the inside, it meant a simple reset wouldn’t behave the same way twice.

    Two merchants doing the exact same thing — using up their included Jack usage on the same day — could have ended up treated differently, purely because of which billing system happened to be under their account. One might get a clean reset. Another might get charged for overage a little early, or a little late, or slightly wrong. Neither merchant would have any way to know that. They’d just quietly be on the unlucky side of a coin flip they never knew was being flipped.

    That’s the part we couldn’t ship. Not because it was risky in an obvious, headline-grabbing way — it’s the opposite kind of risk. Nobody would have filed a support ticket about it, because nobody would have known to. It would have just sat there, quietly unfair, for as long as it took someone to notice a pattern across two accounts they’d have no reason to compare.

    What we built instead

    We built real metered overage billing: usage gets tracked precisely per account, and once a merchant goes past what’s included, they’re billed for the actual extra amount, calculated the same way regardless of which billing system sits underneath their account. It took longer. It’s also the kind of fix where success looks like nothing happening — no one notices metered billing when it’s working correctly, which was exactly the point.

    Why this matters to you

    Next time you’re comparing pricing pages and you see “usage-based” or “overage” pricing on any SaaS tool, it’s worth asking one extra question: how is that overage actually calculated, and is it calculated the same way for every customer?

    Most of the time you’ll never be able to tell from the outside whether the answer is “precisely and consistently” or “close enough, and it varies.” That’s exactly what makes it an easy place for a tool to be quietly inconsistent without anyone catching it — there’s no error message for “you got charged slightly differently than the next customer for the same behavior.” It’s a reasonable thing to just ask, especially for any tool where your usage regularly runs close to what’s included in your plan.

    We’re building yoursignalstack in public, decisions like this included, because we’d rather you see the real process than a highlight reel. If you want to follow along, leave your email and we’ll let you know when it’s live.

    Get notified when yoursignalstack launches →

  • We Built This for One Store. Then We Met the People Running Five.

    Every piece of software starts out quietly assuming its own first user is the only kind of user there is. Ours assumed a store owner: one person, one store, one dashboard. It took an actual human showing up with five stores to point out, politely, that the assumption was incomplete.

    We started hearing from a different kind of user than the one we’d built for: people who don’t run one store. They run several, often for different clients, sometimes under different brands, all at once. Our first version had nothing useful to offer them beyond “log out, log back in as someone else.”

    What “one account, one store” actually meant underneath

    In the original design, an account and a store were basically the same thing. You signed up, you connected your store, and everything downstream of that assumed there was exactly one of it. That’s a completely reasonable assumption for a solo store owner. It falls apart the moment someone needs to look after five stores that aren’t all personally theirs — an agency managing client accounts, or a seller who’s grown into more than one shop.

    For those users, our early setup forced a genuinely bad choice: either share one login across a whole team (which is its own mess — you lose any real sense of who did what, and you can’t cleanly cut someone off when they leave), or open a completely separate account for every single store, with no way to see them side by side.

    Why we didn’t just bolt on a quick fix

    The tempting shortcut was a thin workaround — a dropdown to switch between stores, sitting on top of the same one-account-one-store assumption underneath. We didn’t do that, because it would have papered over the real gap instead of closing it: reporting across stores still wouldn’t have worked cleanly, and access still would have been all-or-nothing.

    So instead we built real multi-store support: one account that can genuinely hold more than one connected store, with real separation between them, so an agency or a multi-shop merchant can see what they’re managing without duct tape holding it together.

    Why this matters to you

    Whether or not you personally run more than one store, this is a genuinely useful question to ask any analytics or marketing tool before you commit to it — because “multi-store support” gets used loosely, and the honest version and the marketing version aren’t always the same thing:

    • Ask what “multi-store” actually means for that specific tool. Does it mean one login where you can see and manage everything in one place — or does it just mean you’re welcome to buy a second subscription and log in twice? Those are very different products wearing the same phrase.
    • If you manage stores for clients, ask about access specifically. Can you give someone access to one store without handing them all of them? If the honest answer is “not really,” that’s worth knowing before you’re relying on it under pressure.
    • If you’re a solo store owner today but might grow into more than one, it’s worth asking the question now anyway. It’s a quick, reliable way to tell whether a tool was actually built with room to grow — or just built for the one customer standing directly in front of it, the way ours originally was.

ClearSellerSignal

Straight talk on ecommerce traffic quality, bot detection, and reading your store data without the hype.

yoursignalstack

Designed with WordPress