A Data Scientist at Zulily plays a pivotal role in driving the algorithms and analytical frameworks that power a highly dynamic, flash-sale e-commerce platform. Unlike traditional retailers with static inventory, Zulily launches thousands of product events daily. This unique business model requires real-time decision-making across merchandising, supply chain logistics, customer personalization, and pricing. As a Data Scientist, you will build the predictive models and optimization engines that directly impact millions of active customers and shape the company's daily revenue trajectory.
The work you do here has a direct line of sight to business value. Whether you are optimizing the recommendation algorithms for the daily email campaigns, forecasting demand for short-lived product events, or building lifetime value models to guide marketing spend, your solutions must scale to handle massive volumes of transactional and behavioral data. You will collaborate closely with product managers, software engineers, and business stakeholders to turn raw data into automated, production-grade systems.
To succeed in this role, you must possess a blend of strong technical execution, business acumen, and the ability to operate in an agile, fast-paced environment. The team values hands-on builders who are comfortable navigating ambiguity and can translate complex machine learning concepts into clear, actionable business strategies.
Initial Screens
reportedMost candidates lose this call inside the first two minutes, during the walkthrough of their own background. The account runs chronologically, sits at the level of tools and titles, and never arrives at a decision anyone could have disagreed with. Anchor on a problem instead of a timeline: what the team could not answer, what you did about it, what happened next. Ninety seconds is enough, and stopping on time leaves room for the half of the call that belongs to you. What you ask about how work gets prioritised signals your level more reliably than the walkthrough does.
What to demonstrate
- Whether your background summary has a shape (problem, decision, consequence) or is a chronological list of tools and employers
- Whether you can account for gaps, short stints and the reason you are looking, unprompted and without hedging
- The substance of the questions you ask back, which an experienced screener reads as a level signal
How to prepare
- Time your opening walkthrough against a clock. If it runs past two minutes, compress the earliest role into a single clause and spend the recovered time on the most recent one
- Write one honest sentence for every gap or short stint visible on your resume and offer it before being asked about it
- Prepare questions about how work arrives and gets prioritised: who writes the request, how often priorities change, and what happens to an analysis after it is delivered
Analytical Assessment
reportedThis round decides whether someone can hand you a schema and a question and trust the number that comes back. Correctness under a clock is the bar, not clever syntax. The habit that separates strong from weak answers is checking the grain: after every join, know how many rows you expect and whether the count moved. Most wrong answers in this format are not wrong logic, they are a fan-out from a key that turned out not to be unique, or a filter applied before an aggregate when it belonged after. Say what you expect before you run it.
What to demonstrate
- Whether your row counts survive each join, and whether you notice on your own when they do not
- Deliberate handling of rows that fail to match, including whether the question needs an inner join or a left join with the non-matches kept and counted
- Whether NULLs are treated on purpose, given that a NULL compares equal to nothing and that COUNT of a column skips it
- Reaching a defensible answer inside the window instead of a refined one after it
How to prepare
- Take a two-table schema, write a join that fans out on purpose, then fix it by collapsing the many-side to one row per key before joining. Repeat until the fix is reflex rather than recall.
- Write a funnel as one query and print the distinct user count at each stage, then confirm each stage is a subset of the one above it rather than assuming it
- Do a few timed runs in a plain text box with no autocomplete and no formatter, since assessment editors often have neither
Onsite Loop
reportedA day of back-to-back interviews samples your floor, not your ceiling. Four hours in, the habits that carry a good answer are the first to go: restating the question before solving it, asking what the data would have to look like, checking a number before quoting it. What the day decides is whether the tired version of you is still someone to leave alone with an ambiguous problem. The round that sinks a candidate is usually not the hardest one. It is the one immediately after the round that went badly.
What to demonstrate
- Whether the late rounds get the same clarifying questions as the first one, or whether you start answering immediately to save effort
- Whether a weak answer stays in the room it happened in, instead of following you into the next conversation as apology or distraction
- Whether the quality of your questions holds up, since fatigue removes curiosity about the problem before it removes knowledge of the method
How to prepare
- Rehearse the length, not just the content: book four mock interviews of different types in one afternoon with short gaps, because the one you need to observe is the fourth
- Put the two or three questions you ask at the start of any problem on a card in front of you, so that under fatigue it is a habit you run rather than a decision you make
- Decide in advance what the gap between rooms is for: water, one line of notes on anything you promised to follow up, and an explicit close on the round that just ended so it does not travel
- Prepare a different closing question for each interviewer, so the end of a long day does not produce the same one four times
PracHub editorial advice for the preparation topics above.
Fitting demand models on sales when sales are censored by availability
Units sold equal the minimum of demand and what was sellable, so every day a SKU was out of stock contributes a zero that looks identical to genuine indifference. A model trained on that history forecasts the stockout, the buy shrinks, availability falls further, and the error compounds each cycle, which is why a declining SKU forecast should always be checked against minutes_unavailable before it is believed. The fixes are to restrict the fit to in-stock periods, to model availability explicitly as an exposure term, or to use a censored likelihood; all three require the availability history to be retained at a finer grain than a daily end-of-day snapshot, which is exactly what teams tend to discard.
Comparing average order value across a change that alters basket composition
Free-shipping thresholds, multi-buy offers and minimum-spend coupons make customers bunch their basket just above a cut-off, so average order value moves because the mix of orders changed, not because anyone is spending more per item. The same trap appears when a change suppresses small orders: average order value rises while total revenue falls. Decompose into units per order and price per unit, look at the whole basket-value distribution rather than the mean (the bunching is visible as a spike at the threshold), and evaluate the change on revenue per session rather than on the conditional mean of orders that happened.
Solving silently instead of narrating the reasoning
Say which branch you are taking and why you chose it over the alternative, for example checking the denominator first because it changes what the comparison means. A correct answer that arrives with no visible path scores below a rigorous one that needed a hint.
Reaching for a model before the target metric exists
Before naming an algorithm, write down the label, the prediction time, and the action that changes when the score crosses a threshold. If you cannot say what decision the output drives, any modelling choice is guesswork dressed up as method.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Walk me through how you would design a customer lifetime value (LTV) m…
Walk me through how you would design a customer lifetime value (LTV) model when historical purchasing data is highly seasonal.
Approach
- Check what information would not exist at prediction time, and exclude it.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
- Set a baseline first, so any model has something honest to beat.
Follow-up
- What would you monitor after launch to know the model is still valid?
- Where could label leakage enter this setup?
How do you evaluate the trade-offs between a simple, interpretable reg…
How do you evaluate the trade-offs between a simple, interpretable regression model and a complex ensemble method in a production environment?
Approach
- Set a baseline first, so any model has something honest to beat.
- Say how the offline result would be validated online before it is trusted.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
Follow-up
- What would you monitor after launch to know the model is still valid?
- How would you choose the decision threshold, and who owns that choice?
Correct a demand estimate for stockout-censored sales history
daily has 180 rows for one SKU at one node: snapshot_date, gross_units_sold, minutes_unavailable (0 to 1440), was_listed (bool), unit_paid_price_cents and is_promo. Recorded sales are the minimum of demand and what was sellable. Estimate the uncensored daily demand rate treating the available fraction of the day as exposure, then estimate the units lost to unavailability over the 180 days. Write the estimator yourself rather than calling a GLM library, and state the assumption the correction rests on.
Approach
- Define exposure_d = was_listed * (1440 - minutes_unavailable) / 1440, in day-equivalents. A day with zero exposure had nothing sellable, so its gross_units_sold is 0, and it contributes 0 to both the numerator and the denominator of the closed-form rate below: it cannot move the estimate in either direction. Drop those days from the fit anyway, because the equivalent log-exposure offset form is undefined at log(0) and any GLM you later swap in will fail on them. Keep every one of them in the lost-units sum, where they carry the largest term.
- Model sales as Poisson with mean lambda * exposure_d. For an intercept-only model with a log-exposure offset the maximum likelihood estimate has a closed form, lambda_hat = sum(sales) / sum(exposure), so no optimiser is needed; write that and derive it from the score equation rather than asserting it.
- Estimate lost units as sum over all 180 days of lambda_hat * (1 - exposure_d), which is the demand the model says arrived while nothing was sellable. Convert to lost revenue only at the unit price actually in force on those days, and mark it as an upper bound.
- State the assumption plainly: demand arrives at a constant rate within the day. It is wrong in the direction that matters, because a SKU that sells out does so after the day's demand has already concentrated in the earlier hours, so scaling by the available fraction understates true demand. End-of-day snapshots cannot distinguish a sellout at 09:00 from one at 23:00.
- Extend to lambda_d = exp(b0 + b1is_promo + b2log(price)) * exposure_d if promo days are a material share, fitting by Newton or by iteratively reweighted least squares, and check the sign of the price coefficient for plausibility before trusting the lost-units figure.
Worked solution 40 min
- Build exposure, then report how many day-equivalents of exposure the 180 calendar days actually contain; if it is 150, a sixth of the history is unobservable.
- Compute naive_rate = gross_units_sold.mean() over all 180 days and lambda_hat = gross_units_sold[exposure > 0].sum() / exposure[exposure > 0].sum(), then assert that dropping the exposure > 0 filter reproduces lambda_hat bit for bit, which is the statement that zero-exposure days carry no information about the rate.
- Compute lost_units = (lambda_hat * (1 - exposure)).sum() over all 180 days, including the zero-exposure ones.
- Bootstrap over days (resample the 180 day-rows with replacement, recompute lambda_hat) for a 95 percent interval on both the rate and the lost-unit figure.
- Sanity-check by recomputing with minutes_unavailable forced to zero, which must return exactly the naive mean.
Follow-up
- Some of the lost demand moved to a substitute SKU or a different node. How would you bound the share that was genuinely lost rather than displaced?
- You only have end-of-day snapshots. What would you instrument to make this estimate honest, and at what data volume?
- The forecast that drove the buy was fitted on this same censored history. Walk through what happens over three consecutive seasons if nobody corrects it.
Given a dataset of customer interactions, write a SQL query to identif…
Given a dataset of customer interactions, write a SQL query to identify the top-performing product categories by daily active users.
Approach
- Compute rates by summing numerator and denominator separately, never by averaging rates.
- State the window function and its partition and ordering out loud before writing it.
- Say which table is the grain you start from, and join outward from it.
Follow-up
- How would you verify this result without re-running the same query?
- How does the query change if the join becomes one-to-many?
How would you handle missing data or extreme outliers in a time-series…
How would you handle missing data or extreme outliers in a time-series dataset using Python or R?
Approach
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- State the window function and its partition and ordering out loud before writing it.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
Follow-up
- How would you verify this result without re-running the same query?
- What breaks if events arrive late or out of order?
Implement a function in Python to clean and preprocess unstructured be…
Implement a function in Python to clean and preprocess unstructured behavioral log data for a recommendation system.
Approach
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- Compute rates by summing numerator and denominator separately, never by averaging rates.
Follow-up
- What breaks if events arrive late or out of order?
- How would you verify this result without re-running the same query?
Contribution margin per delivered order across order, return and shipping costs
Compute contribution margin per delivered order for orders placed in one month, from fct_order_line (order_id, order_line_id, quantity, unit_paid_price_cents, unit_cost_cents, shipping_charged_cents, shipping_cost_cents, tax_cents, payment_method, line_status, placed_at_utc, fx_rate_to_usd) and fct_return_line (order_line_id, quantity_returned, refund_amount_cents, return_shipping_cost_cents, restocking_fee_cents, recovered_value_cents). Shipping columns are already line-level allocations. Assume a processing fee of 2.4 percent of merchandise plus shipping plus tax collected on card, wallet and bnpl, zero otherwise. Attribute refunds to the parent order's placed month. Return per-order margin and the month mean.
Approach
- Pre-aggregate fct_return_line to order_line_id before touching the order lines, summing quantity_returned, refund_amount_cents, return_shipping_cost_cents, restocking_fee_cents and recovered_value_cents. Joining raw would multiply every cost column on the order side.
- Cost all units that were shipped, not only the ones kept. A returned unit was still picked, packed and freighted, so quantity * unit_cost_cents stays in full and only recovered_value_cents comes back on the credit side.
- Treat recovered_value_cents NULL as ungraded, not as zero. COALESCE to zero understates recovery for recent months and makes margin look worse the fresher the data is; either restrict to graded returns or report the ungraded unit count beside the number.
- Compute the processing fee at the line from the amount actually collected, including shipping_charged_cents and tax_cents, and gate it on payment_method so gift_card and cash_on_delivery lines carry none.
- Apply fx_rate_to_usd per line before aggregating, then roll to order_id, restricting the denominator to orders with at least one delivered line.
- Present the per-order margin distribution, not only the mean: a handful of high-value returned orders dominate the average and the median tells a different story.
Worked solution 40 min
- Build returns_by_line with the five SUMs and a COUNT of ungraded (recovered_value_cents IS NULL) rows.
- LEFT JOIN onto delivered order lines placed in the month and compute per-line revenue, cost, recovery, shipping and fee terms in USD.
- Aggregate to order_id, producing net_revenue_usd, cost_usd, recovery_usd, shipping_net_usd, fee_usd and margin_usd.
- Compute the month mean over distinct delivered orders, plus the median and the 10th percentile.
- Report the share of orders whose returns are still ungraded, and restate the mean with those orders excluded.
Follow-up
- Which orders are margin-negative, and is the pattern driven by return rate, discount depth or shipping cost? How would you separate them?
- This excludes warehouse fixed cost and marketing. When does that make the number the wrong one to put in front of a decision?
- Free shipping above a threshold changes both shipping_charged_cents and basket composition. How do you read margin across that change?
How would you approach a dynamic pricing problem for an e-commerce eve…
How would you approach a dynamic pricing problem for an e-commerce event that only lasts 72 hours?
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- State what result would change your recommendation, so the answer is falsifiable.
- Fix the population and the time window before naming any metric.
Follow-up
- How would you detect that the metric is being gamed rather than genuinely improving?
- Which segment would you cut first, and what would that rule out?
What key assumptions must you state and document when presenting an an…
What key assumptions must you state and document when presenting an analytical forecast to business leaders?
Approach
- Fix the population and the time window before naming any metric.
- Decompose the metric into the rates that drive it, and say which one you would check first.
- State what result would change your recommendation, so the answer is falsifiable.
Follow-up
- How would you detect that the metric is being gamed rather than genuinely improving?
- Which segment would you cut first, and what would that rule out?
Design a recommendation system that personalizes the homepage for retu…
Design a recommendation system that personalizes the homepage for returning users in real time.
Approach
- Work from the decision backwards to the evidence you would need.
- Clarify what is being asked and what a complete answer would contain.
- Say what you would check first and why it is the highest-information step.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
Choose the randomisation unit for a signed-out surface
You are testing a size-guide module that is visible to signed-out visitors. Exposure can be keyed on fct_session.session_id, fct_session.anonymous_id, dim_customer.customer_id or dim_customer.household_id. Note that fct_session.customer_id is NULL until sign-in, fct_order_line rows from channel 'store_pos' and 'subscription_autoship' carry session_id NULL, and household_id is non-null for 28 percent of accounts with mean household size 1.4. The primary metric is net revenue per exposed visitor over 30 days. Choose the unit, state what each rejected option breaks, and quantify the variance cost of your choice.
Approach
- Rule out session_id first: a 30-day outcome spans many sessions, so a visitor would be re-randomised on every visit, diluting the contrast toward zero and breaking the independence the variance estimate assumes.
- Rule out customer_id for exposure: it is NULL until sign-in, so a customer-keyed assignment cannot be resolved at the moment the signed-out visitor sees the module. It remains the right unit for a signed-in-only surface.
- Pick anonymous_id as the assignment key, then confront its two leaks. The same person on desktop and on ios_app holds two anonymous_ids and can land in both arms, which attenuates the effect; and orders arriving through store_pos or subscription_autoship carry session_id NULL, so their revenue cannot be attributed to any arm.
- Handle the unattributable revenue explicitly: measure the share of net revenue that cannot be keyed back, confirm it is similar in both arms, and report the estimate as conditional on web-attributable revenue rather than quietly dropping it.
- Handle households by assigning every anonymous_id sharing a household_id to the same arm where the link is known, and clustering standard errors on household_id. Price the cost with the design effect 1 + (m-1) * ICC so the sample increase is a number, not a worry.
Worked solution 30 min
- Assign on anonymous_id, held for the full 30-day window in a persistent bucket rather than recomputed per session.
- Force household consistency: where dim_customer.household_id is non-null, take the arm of the first assigned member for all members.
- Compute the design effect with mean cluster size 1.4 and an assumed intra-household correlation of 0.3: 1 + (1.4 - 1) * 0.3 = 1.12.
- Inflate the per-arm sample by 12 percent and cluster the standard errors on household_id where present, on anonymous_id otherwise.
- Report the attribution gap: the percentage of net revenue from store_pos and subscription_autoship lines with session_id NULL, split by arm, as a pre-declared balance check.
Follow-up
- Cross-device contamination attenuates the measured effect. If 18 percent of exposed visitors see both arms, what does that do to the estimate, and does it make the test conservative or anti-conservative?
- How would you decide whether to reconcile anonymous_id to customer_id retrospectively after sign-in, given that the reconciliation itself is only possible for visitors who converted?
A published cohort number moved with no product change
The 90-day repeat rate for a first-delivery cohort published four weeks ago now reads 29%; the published snapshot says 22%. No product, pricing or lifecycle-email change landed in that window. You have the metric query in version control, the published snapshot table, and the underlying fct_order_line and fct_return_line. Deliverable: determine whether cohort membership changed, the metric definition changed, or the underlying data was restated, and say what you would do to the historical series before anyone reads a trend from it.
Approach
- Separate code from data with one experiment: run the version of the query that produced the published number against today's data, and run today's query against the same data. If old code on new data reproduces 22%, the data is stable and the definition moved; if new code on old data reproduces 29%, same conclusion from the other side.
- Diff cohort membership as a count, not a rate. Cohort membership is fixed at first delivery, so the denominator should be immutable. If it moved, someone re-indexed the cohort on signup or on order placement, or started excluding customers whose first order was later cancelled or fully returned.
- Diff the numerator rule line by line: does a second order have to contain a delivered, not-fully-returned line, or does any placed order count; is the 90-day clock measured from first delivery or from first order; is the window inclusive at the boundary.
- Test for restatement: compare row counts and terminal line_status values for the cohort's order lines then versus now. Late-arriving deliveries and backfilled refunds legitimately move both sides and are not a bug, but they mean the number was published before it was stable.
- Whichever it is, restate the entire history on one definition and annotate the change date on the chart. A series with a step change where the definition moved is worse than no series, because it reads as a result.
Follow-up
- If it turns out to be a restatement rather than a definition change, what publication lag would have prevented it, and what does that lag cost in decision speed?
- How would you make the definition self-documenting so the next person cannot silently change it?
- Someone has already briefed the 29% as a retention win. How do you correct that without the correction itself reading as a result?
Instead of guessing where the week should go, day one measures it under a fixed rubric and allocates the remaining hours in proportion to the gaps. The method is deliberately rigid: the allocation is written down before any studying starts and is not renegotiated when a topic turns out to be unpleasant.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Diagnostic, scored before you study anything
- Sit a 100-minute timed diagnostic in four blocks: 30 minutes of SQL across three prompts, 25 minutes of short-answer statistics, 25 minutes on one modelling or case prompt, and 20 minutes delivering one behavioural story aloud.
- Score each block from 0 to 3 on a fixed rubric where 3 is correct and fluent, 2 is correct but slow or prompted, 1 is partially correct, and 0 is stuck, grading the output rather than how the attempt felt.
- Allocate the hours for days two to five roughly in proportion to 3 minus the score in each block, write the allocation down, and commit to not revising it midweek.
Deliverable: A scored rubric and a fixed hour allocation for the rest of the week.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Largest gap: find the boundary rather than the subject
- Break the weakest area into five named sub-skills (for query work: grain control, window frames, date arithmetic, set logic with NULLs, and reading a query plan) and rate each one, so the rest of the week targets a sub-skill instead of a subject.
- Solve three problems chosen to sit just above where the rating drops off, and for each write the first move you failed to make.
- Re-solve one of them from memory four hours later, on paper, with nothing open.
Deliverable: A five-item sub-skill map with the two blocking sub-skills circled.
Practice prompt ↗Practice prompt ↗03Largest gap: drill the blocking sub-skill
- Do eight short repetitions of the same shape rather than eight different problems, so what you practise is the pattern and not the puzzle.
- Write the rule you now hold in one sentence, then test it against a case built to break it: a ranking function over a column with ties, or a two-sample test on observations that are obviously dependent.
- Have someone else read your one-sentence rule and find the precondition you left out.
Deliverable: One rule statement with its preconditions attached and one counterexample that would have caught the incomplete version.
Practice prompt ↗Practice prompt ↗04Second gap, plus maintenance on your strongest area
- Run the same sub-skill map and boundary protocol on the second-largest gap, compressed into half the day.
- Spend 25 timed minutes on your strongest area to stop it decaying, choosing the hardest problem you can still finish rather than an easy warm-up.
- Compare how the two areas fail: whether you lose time on recall, on setup, or on arithmetic, because the fix differs for each.
Deliverable: A second sub-skill map plus a one-line diagnosis of how each area fails you.
Practice prompt ↗Practice prompt ↗Worked solution ↗05The gap that is not a skill
- Record yourself answering one technical and one behavioural prompt, then count two things in the playback: how many seconds before your first clarifying question, and how many sentences you started without knowing where they ended.
- Rewrite your three most-used stock phrases into shorter versions, and practise saying "I do not know, here is how I would find out" without softening it into a guess.
- Deliver one answer again with a hard 90-second limit to force structure before detail.
Deliverable: Two recordings with a counted improvement in time-to-first-question.
Practice prompt ↗Practice prompt ↗06Retest under day-one conditions
- Sit the same 100-minute diagnostic structure with new prompts of comparable difficulty and score it on the identical rubric.
- Compare block by block, and for any block that did not move, change the method rather than adding hours: a block stuck at 1 usually means the practice was too varied, not too short.
- Write which single block you would still lose the offer on.
Deliverable: A second scored rubric placed next to the first, with one named remaining risk.
Practice prompt ↗Practice prompt ↗07Full loop under interview conditions
- Run a 60-minute mock covering the two blocks that moved least, with an interviewer instructed to interrupt and change direction.
- Write your recovery script for the moment you go blank: restate the question, state your assumption, name the first thing you would check.
- Reduce the week to the rule statements you wrote, each with its preconditions attached, then say every one of them out loud without reading it and cut any you cannot state in a single sentence, since a rule you have to reconstruct mid-answer will not survive being interrupted.
Deliverable: A one-page card holding the recovery script and only the rules you could state from memory.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Data people depend on systems owned by other teams, and much of the job is negotiating for instrumentation, access, or a fix to a broken pipeline. Prepare an example of getting something changed upstream that you did not control. Describe what you asked for, what you traded, and how you worked while you waited.
Tell me about a project where you had to work with incomplete or messy…
Tell me about a project where you had to work with incomplete or messy data. What compromises did you make, and how did you validate your results?
Approach
- Pick a story where you drove the decision, not one where you observed it.
- Close with what you would do differently, concretely.
- Quantify the outcome, including what you would not claim credit for.
Follow-up
- How did you know the outcome was caused by your change?
- What did you decide not to do, and why?
Defend a promotion read that contradicts the revenue number
You analysed a site-wide twenty-percent weekend event. Revenue over the event week rose eleven percent year over year, contribution margin per delivered order fell, and the two weeks after the event ran below the pre-period baseline. The merchandising lead who owns the event calendar has already circulated the revenue figure. You have ten minutes at a planning meeting attended by that lead and their director. Deliver the finding and the recommendation you would make for the next event, and describe how you handle the pushback in the room.
Approach
- Before the meeting, write the finding as one sentence about the event, not about the person who owns it: the event moved price and timing, not demand. Keeping the event owner's judgement out of the sentence is what keeps the holdout you want on the table.
- Open with the number they already have, then decompose revenue into traffic, conversion, units per order, net price per unit and keep rate, and show which term moved. If price per unit fell and units per order held, the revenue gain was volume bought at a lower price.
- Quantify the post-period dip as the pull-forward estimate, and state the measurement window explicitly. The window has to extend past the event because the demand was borrowed from the weeks after it.
- Convert to incremental contribution margin. At gross margin m on list price and discount depth d, holding contribution flat requires a unit lift of d / (m - d), valid when m > d, when the discount applies to every unit sold, when unit cost is constant, and when nothing was cannibalised from full-price SKUs. Compare the observed lift to that threshold.
- Say what would change your mind and propose the design that would settle it: a geo or customer holdout on the next event, with the number of units and weeks it needs.
- End on the next event, not a verdict on the last one, so the meeting produces a decision rather than a defence.
Follow-up
- The lead says the event acquired new customers whose lifetime value justifies the margin loss. How would you test that claim with dim_customer and fct_order_line?
- Your director wants one number to take to finance. Which one, and what caveat travels with it?
Tell a team their test cannot be read before Friday
A checkout test has run eleven days. Conversion is 2.4 percent in control and 2.7 percent in treatment, and the team wants to ship on Friday. Revenue per visitor is higher in treatment, driven by a small number of very large baskets, and the return window on those orders has not closed. The engineering lead has already announced the win internally. You are asked for sign-off. Give your answer, the evidence behind it, and a path that lets them ship without pretending the result is something it is not.
Approach
- Compute rather than assert. State the minimum detectable effect the observed sample supports at a 2.4 percent baseline, then say whether a 0.3 point absolute lift sits inside or outside it. An objection without that number reads as caution and loses to a launch date.
- Separate the two problems, because they have different fixes. Conversion may simply be underpowered. Revenue per visitor is a different failure: the mean is driven by the tail, so it needs a cap declared before the data was seen or a bootstrapped interval, and a cap chosen now is not a cap.
- Run the mechanical checks first because they are cheap and they end arguments: sample ratio mismatch, the triggered-population definition, and whether both arms drew on the same constrained inventory.
- Quantify the return exposure concretely: the share of treatment revenue sitting in orders whose return window is open, and what the category's matured net unit return rate would do to the lift if applied to it.
- Offer a path rather than a veto. If the change is reversible and the downside is bounded, ship it, with the read scheduled at return maturity and the decision rule written down now, before anyone knows which way it goes.
- Handle the premature announcement quietly and separately. It is a fact to correct, not a position to negotiate against, and making it the topic guarantees the measurement argument is lost.
Follow-up
- The team says the large baskets are real revenue and capping throws away the win. What is your answer?
- What decision rule would you write down today so this same conversation does not happen on the next test?
- 01
Tell me about a project where you had to work with incomplete or messy data. What compromises did you make, and how did you validate your results?
- 02
You analysed a site-wide twenty-percent weekend event. Revenue over the event week rose eleven percent year over year, contribution margin per delivered order fell, and the two weeks after the event ran below the pre-period baseline. The merchandising lead who owns the event calendar has already circulated the revenue figure. You have ten minutes at a planning meeting attended by that lead and their director. Deliver the finding and the recommendation you would make for the next event, and describe how you handle the pushback in the room.
- 03
A checkout test has run eleven days. Conversion is 2.4 percent in control and 2.7 percent in treatment, and the team wants to ship on Friday. Revenue per visitor is higher in treatment, driven by a small number of very large baskets, and the return window on those orders has not closed. The engineering lead has already announced the win internally. You are asked for sign-off. Give your answer, the evidence behind it, and a path that lets them ship without pretending the result is something it is not.
Is this an official Zulily interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at Zulily. Rounds and questions reflect what candidates have reported, not a process Zulily has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How technical is the coding portion of the interview?
The coding interviews focus primarily on practical data manipulation, SQL queries, and basic algorithm implementation. You do not need to worry about highly complex competitive programming puzzles, but you must write clean, efficient, and bug-free code to solve data manipulation tasks.
PracHub interview research ↗What is the company culture like for Data Scientists?
The culture is highly collaborative, fast-paced, and data-driven. Data Scientists are expected to be highly autonomous and take end-to-end ownership of their projects, from initial data discovery to final production deployment.
PracHub interview research ↗How should I prepare for the analytical Excel test if it is included in my process?
Focus on speed, clarity, and structured logic. Practice building clean financial or analytical models under a strict time limit, and make sure to clearly label your inputs, formulas, and key assumptions so that an interviewer can easily audit your work.
PracHub interview research ↗How long does the interview process typically take?
The entire process, from the initial application to a final decision, generally takes about three to four weeks, depending on candidate availability and scheduling logistics.
PracHub interview research ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
platform · Accessed 2026-09-22 - 02PracHub Data Scientist practice ↗
Cross-company practice questions for this role.
platform · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
platform · Accessed 2026-09-22