Marketplace

Marketplace

Ecommerce8 data marts66 fields9 calculated fieldsView on GitHubVlad FlaksRus Obolonsky

Buyer7 fields2 relationshipsCancellations7 fields1 relationshipCategory4 fields4 relationshipsListings7 fields3 relationshipsOrders15 fields7 relationshipsReviews6 fields1 relationshipSearch Requests10 fields3 relationshipsSeller10 fields3 relationships

Buyers and sellers meet through listings and search, with every order carrying gross merchandise value, take rate and seller payout, alongside the unmet searches, unsold listings and ratings that show where the match breaks down.

Hand this to your AI

GMV keeps growing while buyers search and find nothing, and no report shows which categories are short of supply.

Paste this into your AI assistant. It builds the Marketplace model's Data Marts in your data warehouse from your platform data, and shows which categories have buyers searching but too few live listings.

The prompt

build the Marketplace model with its Search Requests, Listings and Category Data Marts, then show me which categories have buyers searching but too little live supply to fill the demand

Overview

A two-sided online marketplace modeled end to end: independent buyers and independent sellers matched through listings and search, with every order carrying the full economics — gross merchandise value, the category take rate, the platform's cut and the seller's payout. Around that match sit the signals that tell you whether the two sides are actually clearing: what buyers searched for and failed to find, which listings never sold, which orders fell through before settling, and what the ratings say afterwards. Together they let you follow both sides of the flywheel — where demand goes unmet, and where supply gives up.

How this business is managed

  • Supply — grows the number of sellers who actually sell, and keeps their catalogues live while they do.
  • Demand — turns buyers' searches into orders, and brings the buyers who order back for a second one.
  • Trust & Safety — keeps orders from being cancelled after they are placed, and buyers from ending up with a complaint.

Key metrics

Key Data Marts

  • Orders — every match of a buyer to a seller's listing, with its full economics.
  • Search Requests — the demand that arrives, and how much of it ends in an order.
  • Seller — the supply side, and where each seller is in its life on the platform.
  • Listings — the catalogue buyers can order from today.

Example Questions

  • Where is liquidity weakest — which categories have buyers searching but too little live supply to fill the demand?
  • Is take-rate optimisation costing us supply, with sellers in our highest-commission categories going dormant faster than the rest?
  • How much of our booked GMV never settles, and do cancellations and complaints concentrate around the same sellers?

Explore on canvas →

Relevant Data Sources

Buyer Data Mart

Buyer

The demand side of the marketplace: one row per registered buyer, carrying how they were acquired, where they are, and how much they have transacted. Lifetime order count and a repeat flag make demand-side retention a first-class field — most buyers place a single order and never return, and the share who come back for a second is the health number every marketplace watches.

Fields

ColumnTypeAliasDescription
buyer_idSTRINGBuyer IDPK. Unique buyer identifier.
signup_dateDATESignup DateWhen the buyer first registered.
acquisition_channelSTRINGAcquisition ChannelMarketing source that brought the buyer in.
regionSTRINGRegionBuyer's geographic region.
segmentSTRINGSegmentBuyer segment (one-time, occasional, regular, power).
lifetime_ordersINTEGERLifetime OrdersTotal orders the buyer has placed to date.
is_repeatBOOLEANIs RepeatWhether the buyer has placed 2+ orders — demand-side retention.
repeat_buyer_shareFLOATRepeat Buyer Share

Calculated Field. Share of ordering buyers who placed two or more orders, lifetime, as a 0–1 fraction. Registered buyers who never ordered are left out of both sides, so the rate reads retention, not activation. Recent signup cohorts read lower because they have had less time to reorder.

SAFE_DIVIDE(COUNTIF(is_repeat), COUNTIF(lifetime_orders >= 1))

Cancellations Data Mart

Cancellations

One row for every order that was cancelled — and only those. Each row records who pulled the plug (buyer, seller or platform), at which stage (pre-payment, pre-fulfilment or in-transit), the stated reason, and how much was refunded. Because refund magnitude scales with stage — near zero pre-payment, close to full once fulfilment is underway — this is where an ops or trust-and-safety lead finds the fixable concentration of fill-rate failures.

Fields

ColumnTypeAliasDescription
cancellation_idSTRINGCancellation IDPK. Unique cancellation identifier.
order_idSTRINGOrder IDOrder that was cancelled. FK to Orders
cancelled_atTIMESTAMPCancelled AtWhen the cancellation happened.
cancelled_bySTRINGCancelled ByWho cancelled: buyer, seller or platform.
stageSTRINGStageOrder stage at cancellation: pre-payment, pre-fulfilment or in-transit.
reasonSTRINGReasonStated cancellation reason.
refund_amountNUMERICRefund AmountAmount refunded to the buyer (never more than the order's gmv).
sellers_with_cancellationsINTEGERSellers With Cancellations

Calculated Field. Distinct sellers behind the cancelled orders in the selected rows, read through the order. Filter Cancelled By to seller for sellers who cancelled their own orders. A distinct count across the join: rows do not add up to the total.

COUNT(DISTINCT orders.seller_id)

Relationships

Related data martOnCardinalityMeaning
Ordersorder_id = order_idN:1The order that was cancelled.

Category Data Mart

Category

The category tree every listing and order is filed under, and — crucially — the standard take rate the platform charges on sales in each category. Take rate is the biggest lever a category manager holds: raise it and revenue per order rises, but the sellers in that category feel the squeeze. Rates follow real marketplace norms — physical goods sit lower (8–15%), while services and premium or handmade categories carry a higher cut (15–22%).

Fields

ColumnTypeAliasDescription
category_idSTRINGCategory IDPK. Unique category identifier.
nameSTRINGNameDisplay name of the category.
parent_categorySTRINGParent CategoryParent grouping in the category tree (Goods, Media, Services).
take_rate_pctFLOATTake Rate %Platform's standard commission for the category, as a percent (e.g. 12.0 = 12%) — the take-rate optimisation lever.

Listings Data Mart

Listings

One row per listing, the unit of supply a buyer actually orders. Each listing belongs to a seller and a category and carries a price and an availability state. The count of live listings per seller is exactly that seller's active inventory, which makes this the backbone behind every order's price and category — and the first place to look when searches arrive and find nothing to buy.

Fields

ColumnTypeAliasDescription
listing_idSTRINGListing IDPK. Unique listing identifier.
seller_idSTRINGSeller IDSeller that owns the listing. FK to Seller
created_atTIMESTAMPCreated AtWhen the listing was created.
category_idSTRINGCategory IDCategory the listing belongs to. FK to Category
priceNUMERICPriceListed price of the offer.
statusSTRINGStatusCurrent listing status: active, paused, sold_out or removed.
is_availableBOOLEANIs AvailableWhether the listing is live inventory — supply availability.

Relationships

Related data martOnCardinalityMeaning
Categorycategory_id = category_idN:1The category this listing is filed under.
Sellerseller_id = seller_idN:1The seller who owns this listing.

Orders Data Mart

Orders

The match at the heart of the marketplace: one row per order placed, tying a buyer to a seller's listing. It carries the full transaction economics — gross merchandise value, the category take rate, the platform's cut and the reciprocal seller payout. Revenue is recognised only on orders that settle: a cancelled order keeps its booked GMV for funnel analysis while its net GMV, platform revenue and seller payout all fall to zero, so gross and net are never confused.

Fields

ColumnTypeAliasDescription
order_idSTRINGOrder IDPK. Unique order identifier.
buyer_idSTRINGBuyer IDBuyer on the order. FK to Buyer
seller_idSTRINGSeller IDSeller on the order (always the listing's owner). FK to Seller
listing_idSTRINGListing IDListing that was purchased. FK to Listings
category_idSTRINGCategory IDCategory of the purchased listing, denormalised for slicing. FK to Category
ordered_atTIMESTAMPOrdered AtWhen the order was placed.
quantityINTEGERQuantityUnits ordered (gmv = listing price × quantity).
gmvNUMERICGMVGross merchandise value booked for the order.
take_rateFLOATOrder Commission RatePer-order commission rate, as a 0–1 fraction — the category's standard rate (category take_rate_pct / 100), kept even on a cancelled order that earns nothing. For take rate across orders use Take Rate (net_take_rate), never an average of this field.
platform_revenueNUMERICPlatform RevenuePlatform's recognised revenue (gmv × take_rate; zero if cancelled).
seller_payoutNUMERICSeller PayoutSeller's take-home (gmv − platform_revenue; zero if cancelled).
net_gmvNUMERICNet GMVGMV net of cancellations (equal to gmv unless cancelled, then zero).
statusSTRINGStatusOrder status: pending, fulfilled or cancelled.
is_fulfilledBOOLEANIs FulfilledWhether the order was fulfilled.
fulfillment_minsFLOATFulfillment Time (min)Order-to-fulfilment time in minutes — fill speed (null unless fulfilled).
net_take_rateFLOATTake Rate

Calculated Field. Platform revenue as a share of net GMV, as a 0–1 fraction — commission earned per dollar of GMV net of cancellations, pending orders included. A ratio of sums, so a large order weighs more than a small one; averaging Order Commission Rate (take_rate) typically overstates it, because low-commission categories carry the biggest baskets.

SAFE_DIVIDE(SUM(platform_revenue), SUM(net_gmv))
cancelled_ordersINTEGERCancelled Orders

Calculated Field. Orders cancelled before settling, counted at whatever grain the report asks for. The numerator of Cancellation Rate.

COUNTIF(status = 'cancelled')
cancellation_rateFLOATCancellation Rate

Calculated Field. Share of orders placed that were cancelled, as a 0–1 fraction — by order count, not by value. Reads Cancelled Orders, so the two always agree.

SAFE_DIVIDE(cancelled_orders, COUNT(order_id))
aovFLOATAverage Order Value

Calculated Field. Net GMV per non-cancelled order. Cancelled orders leave both sides, so a wave of cancellations does not drag the basket size down; pending orders count, because their GMV is still booked.

SAFE_DIVIDE(SUM(net_gmv), COUNT(order_id) - cancelled_orders)
active_sellersINTEGERActive Sellers

Calculated Field. Distinct sellers with at least one non-cancelled order in the selected rows — supply that actually sold. A distinct count: rows do not add up to the total, because one seller sells in several categories and months.

COUNT(DISTINCT IF(status != 'cancelled', seller_id, NULL))
order_size_bandSTRINGOrder Size Band

Calculated Field. Small, Medium, Large or Premium, from the order's gross GMV. A row-level formula that behaves as a dimension: group and filter by it. Bands are the order-value quartiles at round dollar edges.

CASE WHEN gmv < 50 THEN 'Small (under $50)' WHEN gmv < 100 THEN 'Medium ($50-99)' WHEN gmv < 250 THEN 'Large ($100-249)' ELSE 'Premium ($250+)' END
gmv_per_active_sellerFLOATGMV per Active Seller

Calculated Field. Net GMV per seller who made a sale, in dollars — supply productivity. Reads Active Sellers, so the divisor is a distinct count: recompute it at each grain, never sum or average the rows.

SAFE_DIVIDE(SUM(net_gmv), active_sellers)

Relationships

Related data martOnCardinalityMeaning
Buyerbuyer_id = buyer_idN:1The buyer who placed this order.
Categorycategory_id = category_idN:1The category this order is filed under.
Listingslisting_id = listing_idN:1The listing that was ordered.
Sellerseller_id = seller_idN:1The seller who fulfilled this order.

Reviews Data Mart

Reviews

One row per review left after a fulfilled order — the marketplace's trust signal. Only a minority of completed orders are ever reviewed, since reviewing is voluntary, and ratings follow the familiar J-shape: mostly five stars, a hard bump at one star, little in between. The reviewer role separates the buyer's rating of the seller from the seller's rating of the buyer, and the complaint flag — concentrated in the low ratings — marks where trust is breaking down.

Fields

ColumnTypeAliasDescription
review_idSTRINGReview IDPK. Unique review identifier.
order_idSTRINGOrder IDOrder the review relates to (always a fulfilled order). FK to Orders
reviewer_roleSTRINGReviewer RoleSide that left the review: buyer or seller.
ratingINTEGERRatingStar rating 1–5 for the order.
created_atTIMESTAMPCreated AtWhen the review was submitted.
has_complaintBOOLEANHas ComplaintWhether the review flags a complaint (concentrated in 1–2 star ratings).

Relationships

Related data martOnCardinalityMeaning
Ordersorder_id = order_idN:1The fulfilled order being reviewed.

Search Requests Data Mart

Search Requests

One row per search a buyer runs — the top of the demand funnel and the cleanest read on marketplace liquidity. Each request records the category searched, how many results came back, whether the buyer clicked, and whether the search converted into an order, along with the time it took to match. Searches that return nothing, or return results but never convert, are the "demand with no fill" signal a liquidity analyst hunts for; the live supply they could have found is in Listings.

Fields

ColumnTypeAliasDescription
request_idSTRINGRequest IDPK. Unique search request identifier.
buyer_idSTRINGBuyer IDBuyer who made the search. FK to Buyer
category_idSTRINGCategory IDCategory the search was scoped to. FK to Category
requested_atTIMESTAMPRequested AtWhen the search was made.
querySTRINGQueryRaw search text entered by the buyer.
results_countINTEGERResults CountNumber of results returned.
clickedBOOLEANClickedWhether the buyer clicked a result.
convertedBOOLEANConvertedWhether the search led to an order.
order_idSTRINGOrder IDOrder the search converted into, if any. FK to Orders
time_to_match_minsFLOATTime to Match (min)Search → transaction latency in minutes (null unless converted).

Relationships

Related data martOnCardinalityMeaning
Buyerbuyer_id = buyer_idN:1The buyer who ran this search.
Categorycategory_id = category_idN:1The category searched in.
Ordersorder_id = order_idN:1The order this search led to, where it converted.

Seller Data Mart

Seller

The supply side: one row per seller, with the primary category they sell in, their buyer rating, how many listings they keep live, and — critically for supply-health work — when they last sold and whether they are still active. Supply is heavily concentrated: a small share of sellers drives most of the platform's GMV, so lifecycle status (active, dormant or churned, driven by the recency of their orders, or unactivated until the first sale) is where a supply manager looks first when GMV softens.

Fields

ColumnTypeAliasDescription
seller_idSTRINGSeller IDPK. Unique seller identifier.
onboarded_atDATEOnboarded AtWhen the seller joined the platform.
category_idSTRINGCategory IDPrimary category the seller sells in. FK to Category
regionSTRINGRegionSeller's geographic region.
ratingFLOATRatingAverage buyer rating of the seller (null until first review).
active_listingsINTEGERActive ListingsNumber of currently live listings.
is_activatedBOOLEANIs ActivatedWhether the seller has reached its first sale — supply activation.
fulfillment_typeSTRINGFulfillment TypeHow the seller fulfils orders.
last_sale_atDATELast Sale AtDate of the seller's most recent sale (null if never sold).
statusSTRINGStatusLifecycle state from sale recency: active (sold in the last 30 days), dormant (31–90 days), churned (more than 90 days) or unactivated (never sold).

Relationships

Related data martOnCardinalityMeaning
Categorycategory_id = category_idN:1The seller's primary category.

Apply to your project

  1. 1

    Install the Import Model plugin

    One plugin, installed once, in your own OWOX workspace.

    Get the plugin →

  2. 2

    Import this model

    Point it at this bundle and it creates every data mart above, joins and all.

    Open the model →

  3. 3

    Plug in your data and destinations

    Connect your own sources and send the results where your team already works.

    Browse connectors →

4. Optional — customize as you wish. Rename a column, drop a mart, add your own: once it is imported it is yours, and nothing here syncs back.

Customer stories