BigQuery and Slack: which metric moves were explained, and where
The weekly business review starts in forty minutes. The analytics engineer has the BigQuery console open on the left screen: a query over analytics.checkout_sessions, grouped by day and country, six weeks back. UK checkout conversion sat between 3.0 and 3.2 percent for a month, dropped to 2.4 percent on Thursday, and stayed there. The other four markets are flat.
On the right screen is Slack, and somewhere inside it is the reason. The head of growth already asked in #growth yesterday: "does anyone know what happened to UK checkout?" Two people replied with guesses. Nobody linked anything.
What the analytics engineer needs to say in the review is not "conversion is down 0.7 points". Everyone can read that off the chart. The question the CFO actually asks is narrower: of the moves in this deck, which ones do we already understand, and which ones is nobody looking at? Answering that means holding a list of metric movements in one hand and six weeks of #checkout-eng, #deploys, #incidents and #growth in the other, then deciding which sentence belongs to which number.
That is twenty minutes of scrolling on a good day. Usually it does not happen, and the dips nobody explained become the dips nobody owns.
What BigQuery shows on its own, and where it stops
BigQuery is very good at the first half. It holds the events, the sessions, the orders, the spend. With a window function you can compare each day against its own trailing average per country and rank the deviations. ML.DETECT_ANOMALIES will flag the outliers for you without hand tuning thresholds. Scheduled queries can keep a rolling anomalies table warm. CONTRIBUTION_ANALYSIS will even tell you which segment combination carries most of the difference between two periods, so you learn that the drop is not "the UK", it is UK plus mobile plus new customers.
That is a precise description of the shape of the move. It tells you where to look. It does not tell you what happened.
The wall is not a query-language limit, it is a data limit. BigQuery can only reason over what got written into a table. A deploy at 14:20 on Thursday is a row only if someone built a pipeline that makes deploys rows. A payment provider degrading in one region is a row only if you ingest their status feed. The sentence "we shipped the new address validation, postcode field is rejecting some valid UK formats" is not a row anywhere, and if you loaded it into a STRING column the column you actually want, the one that says what this claim explains, is exactly the one you cannot populate by loading text.
What Slack shows on its own, and where it stops
The explanation almost always exists in Slack, and it usually appears within an hour of the cause. Someone posts the deploy. Someone pastes the vendor status page. Someone says "we paused the Meta spend, CAC was ugly". Support says "we are getting a lot of postcode complaints this morning". Slack search is genuinely capable: in:#checkout-eng after:2026-06-25 before:2026-07-02, saved threads, canvases, and on paid plans AI summaries of a channel you missed.
Where it stops is the other half. Slack does not know that conversion moved. It has never seen the number. It cannot rank messages by "closest to a 22 percent deviation in UK mobile checkout on Thursday" because that series does not exist inside it, so it ranks by keyword relevance instead.
Which means you have to already suspect the cause to type the right search. Search "conversion" and you get every time anyone used the word, mostly in unrelated contexts. Search "address validation" and you find it instantly, but only because you already knew. Slack is an excellent answer key that cannot be indexed against the question.
Why the gap is structural
Line the two halves up and it is obvious that they are different kinds of object.
| The metric move | The explanation | |
|---|---|---|
| Lives in | BigQuery tables | Slack messages |
| Form | A record: typed, keyed, timestamped | A sentence somebody wrote, in prose |
| Retrieved by | Filtering and aggregating | Reading, or keyword luck |
| Knows about the other side | No | No |
| Complete? | Only what was instrumented | Only what someone bothered to type |
The usual integrations move traffic in one direction. A scheduled query posts a chart into a channel every Monday. That is distribution, and it is useful. Nothing carries the channel's understanding back to the number.
It is worth being precise about why the adjacent categories do not close this either, because both are good at what they do. Automation platforms like Zapier and Make are trigger based: something happens, then steps run and records move forward. That architecture is built to advance work, not to look backward at a period that has already closed and account for it. BI tools like Looker and Power BI connect to databases and modelled sources, which is the right design for numbers, and it means an unmodelled sentence in a channel is not something they see poorly. It is outside what they can see at all.
So this is not a reporting feature either product forgot to build. It is a join between a table and a conversation, and the join condition is a judgement.
What the join actually requires
Two things, and only one of them is mechanical.
The key is time plus scope. For each flagged movement you need a window that opens before the move, not on it, because deploys precede their effects and because people discuss a change before making it. Two days earlier to one day later is a reasonable default. Scope narrows the candidate set to the channels that could plausibly own the surface in question: engineering channels for the checkout path, growth for spend, incidents for anything vendor-side.
That leaves maybe forty messages per flagged day. The second thing is the part no key can do. Someone has to read those forty messages and decide whether any of them plausibly accounts for this number. "Address validation shipped Thursday" explains "UK mobile checkout fell Thursday" only if you know that address validation sits on the checkout path and that UK postcodes are the format most likely to fail a naive validator. A keyword match returns everything or nothing. Comprehension returns the two messages that matter, and flags honestly when there are none.
Doing it with Skopx
Skopx sits over both sides, BigQuery and Slack among nearly 1,000 connected tools, and answers with citations back to the rows and the messages it used. The realistic thing someone types in chat before the review is long, because the question is:
Pull daily checkout conversion by country from BigQuery for the last six weeks. Flag any day a country moved more than 15 percent against its own trailing 14 day average. For each flagged day, read #checkout-eng, #deploys, #incidents and #growth from two days before to one day after, and tell me which message, if any, explains the move. List the flagged days with no plausible explanation separately.
What comes back is a short table of movements, each with the message that accounts for it and a permalink to the thread, plus the SQL that produced the number. The last section is the useful one: the moves nobody wrote anything about. In the example above, the UK drop resolves to a deploy thread from Thursday 14:20, and a smaller 12 percent dip in Germany the week before turns out to have no explanation anywhere, which is the item that actually belongs in the review.
When you want that same reading available without retyping it, ask in chat for a console over it and you get one built as an internal app: flagged moves down the left, each row opening to the query behind the number and the candidate messages beside it, filters by market and channel, and a plain marker for explained, unexplained or disputed. It reads live when someone opens it. The one thing it writes is a button a person presses, with a confirmation step: post the unexplained list into #analytics, or reply in the deploy thread asking the owner to confirm the link. Team is $16 per seat per month with 2.3 million AI tokens included, Solo is $5.
Honest limits
It proposes, a person confirms. Temporal coincidence is not causation, and a deploy that landed the same afternoon as a drop is a candidate, not a verdict. The output is designed to be argued with in the review, which is the correct place for it.
It stores nothing. The console holds no state between sessions, keeps no history table of past explanations, and does not run on a schedule or send alerts. Marking a move explained is a message posted into Slack, not a record saved somewhere. If you want a durable annotation log, that belongs in your warehouse and is a different piece of work.
It can only read what the connected Slack account can read. The real explanation is frequently in a DM between two engineers, or in a private channel, and in those cases the honest answer is "no explanation found in the channels I can see", which is at least accurate.
Explanations nobody wrote down do not exist for this. If the cause was diagnosed on a call and fixed without a message, no tool recovers it.
And it will not find slow drifts. It finds step changes against a threshold you chose. A conversion rate that decays two percent a month for a year passes every check here and still costs you more than any single Thursday.
Skopx Team
The Skopx engineering and product team