What this add-on does
Someone is looking at a vintage denim jacket and wants to know whether it will fit across the shoulders. On a marketplace they need the person who owns it — and if there is no way to reach them on your site, they find one elsewhere, or they do not buy.
Three connected things:
- An inbox. A threaded buyer↔vendor conversation attached to the item being discussed, with image attachments, at
/dashboard/messages/. - Offers. A buyer proposes a price; the vendor accepts, declines or counters; an accepted offer is what the buyer is charged at checkout.
- A contact-detail filter. Optional screening of message text for email addresses, phone numbers, social handles and off-site links.
It is £7 rather than the usual £5 because it is two features in one, sold together because an offer is a message: created in a thread, answered in a thread, read in a thread.
Why Dokan can't do this on its own
Dokan Lite has no buyer↔vendor chat. That is not a criticism — Dokan is an excellent free multivendor plugin and this add-on sits alongside it. But Store Support is a ticketing system: useful after a sale, and it does not read like a conversation, so buyers do not use it before they buy.
Live Chat is a paid module that connects your marketplace to somebody else's chat product — Facebook Messenger, or TalkJS. That works, and for some marketplaces it is the right answer. It also means your buyers' and sellers' conversations are held by a third party: their pricing, their uptime, a Facebook account for your sellers, and messages that are not yours to search, moderate or export.
BazaarKit's inbox is first-party. Conversations, offers and attachments are rows and files on your own hosting.
The inbox
A conversation starts from a product page. Beneath the price, a logged-in shopper who is not the seller sees Message seller; guests see the same link, which sends them to log in and returns them to the item. The seller of that item never sees a button to message themselves, and the link appears whether the item is in stock or sold out — "do you have another one of these?" is one of the most common messages any marketplace receives.
/dashboard/messages/. Offers appear as cards inline in the thread — here a £28.00 offer that was declined.Unread counts, a last-message preview on each row, mark-as-unread, and a per-person delete that hides a thread for you without destroying it for the other party. Either side can block the other, stopping contact both ways until they unblock. Notification emails use WordPress's own mail, throttled to one per recipient per thread per ten minutes; offer emails skip the throttle, because being told your offer was accepted should not wait.
Image attachments, and how they stay private
Sellers send photographs constantly: a mark on a sleeve, proof of postage. Attachments are JPG, PNG, GIF or WEBP, up to 8 MB. Where they go is the unusual part, because a message photo can be someone's front door or a receipt with an address on it:
- A separate deny-all folder with direct web access blocked, and a random prefix on every filename. The deny rule only works on Apache-style servers, so an unguessable name is an independent second defence —
passport-scan.jpgdoes not stay guessable where the rule is inert. - Signed, expiring links. Images are served through one endpoint requiring a signature over the image, its size and an expiry, generated only inside the conversation — so only the two participants ever hold a working URL, and a leaked link stops working within days.
- Kept out of the media API. WordPress will list unattached uploads to anonymous callers; message attachments are excluded, and refused on direct reads for anyone but the uploader or an administrator.
- Tidied automatically. A daily job deletes images uploaded but never sent, once they are over 48 hours old.
Offers and counter-offers
The jacket is listed at £35. A buyer thinks it is worth £28.
- The buyer presses "Make an offer" and types £28. It must be below the listed price and at least half of it, so £3 on a £35 jacket is refused before the seller sees it. One live offer per person per item.
- The offer lands in the thread as a card and the seller is emailed. It is now the seller's turn, and only they can act on it.
- The seller accepts, declines or counters with their own figure — say £31 — which passes the turn back to the buyer. This continues as long as both keep answering.
- An unanswered offer expires after 48 hours, and every counter restarts that clock. Once declined or lapsed, the buyer can start a fresh one from inside the thread.
- On acceptance the price is held for 48 hours and the buyer gets a "buy now at the agreed price" action, which adds the item to the ordinary WooCommerce basket.
- The agreed price is what they pay. It is read from the offer record on your server at basket-calculation time, never from anything the browser sends, so a buyer can only pay a price a seller genuinely granted. Once ordered, the offer is spent.
Only the buyer is held to the 50% floor. A vendor countering below half their own list price is discounting their own item, which is theirs to decide.
An accepted offer covers one unit. Put two of that item in the basket and the line reverts to the list price — otherwise £5 off a £50 item plus a quantity of ten would hand over £500 of goods for £50. The offer is not burnt: the buyer can still take it on the single item it was agreed for.
Turning offers off — and what that does not break
Plenty of marketplaces do not want haggling: handmade goods, regulated products, anything where a fixed price is part of the promise. So offers are a switch, not a separate purchase. Untick Let buyers make an offer and negotiate a price and the button disappears from product pages and threads, while the endpoint behind it refuses new offers too — a hidden button is not the only thing in the way. Messaging carries on exactly as before.
What the switch deliberately does not stop:
- Accepted offers are still honoured at checkout. A buyer holding an accepted £28 still pays £28; charging them £35 because an administrator changed a setting would be reneging on your own deal.
- Negotiations under way can still be concluded — the seller can accept or decline what is on their desk. Countering is blocked, because a counter concludes nothing: it proposes a new price, which is starting a negotiation by another name.
- Open offers still expire on schedule, so nothing sits pending forever in a seller's list.
- Nothing is deleted. Turn it back on and everything is where you left it.
The same holds if the add-on stops running: switch the module off or let a subscription lapse, and accepted prices are still honoured and open offers still age out. A lapsed licence must not break a promise your marketplace already made to a buyer.
The contact-detail filter
This is the part most marketplace owners come looking for and cannot find. The filter screens the text of every message and reaches one of three verdicts: clean messages pass untouched, hard verdicts block the message and tell the sender why, and soft verdicts allow it and email you about it.
What it catches
- Email addresses — direct, and the usual disguises:
jane[at]gmail.com,jane at gmail dot com. - Social and messaging handles —
wa.me,t.meandm.melinks, a named platform followed by a handle (WhatsApp, Instagram, Snapchat, Telegram, TikTok, Kik, WeChat, Viber, Messenger), and a bare@handlecontaining at least two letters. - Off-site links — anything pointing at a host that is not your own site, including links with
https://stripped off. As much a phishing control as a commission one: a fake "marketplace support" message dropping a lookalike payment link into a thread is an attack every marketplace eventually sees. - Phone numbers — with a deliberate condition, below.
Text is normalised first: entities decoded, invisible zero-width characters stripped, unusual spaces flattened, non-Latin digits folded. Without it, a zero-width space between each digit of a phone number is invisible to the reader and to the filter alike.
Why phone numbers are treated differently
"A long run of digits is a phone number" falls apart on a real marketplace within a day: tracking codes, order references, ISBNs, model numbers and a list of clothing sizes are all that length, and blocking those is a more common and more damaging mistake than missing one number.
So a phone-length run on its own is reported to you but allowed. It is blocked only when the message also asks to be contacted ("call", "text", "WhatsApp", "reach me", "my number"), or carries an international dialling prefix like +44, or is spelled out in words — nobody writes a tracking code as "oh seven nine one one" unless they are getting round something.
Things left alone on purpose, each a real false positive found in testing: "washing at 30.Do not tumble dry" is not an email address, "the snap button is missing" is not Snapchat, "a small line down the front" is not a Line handle, "DHL tracking is 1234567890" is not a phone number, and "meet @3pm today" is not a social handle.
Rolling it out without false-positive chaos
Both filter settings ship off, so installing the add-on changes nothing until you decide otherwise. When you do, use this order — it is what the settings screen itself recommends.
- Tick both boxes at once — the filter, and monitor-only mode. That combination detects and alerts, but never blocks a message.
- Leave it a week and read the alerts. Each says what was detected, whether it would have been blocked, who sent it, and a short extract.
- Judge it on your own traffic. A parts marketplace is full of serial numbers; a clothing marketplace is full of size lists. The alerts show what enforcement would have cost you.
- Only then untick monitor-only. Hard verdicts are refused from that point, and the sender is asked to keep the conversation on the marketplace so their order stays protected.
Alerts go to your WordPress admin email address, throttled to one per sender per ten minutes.
Two honest limits. The words it recognises — digit words and "telephone me" verbs — are English, so on a non-English marketplace the phone rules under-detect rather than over-block. And attachments are not screened: there is no text recognition on images. When a message arrives as an image with no text at all you get an alert saying exactly that, rather than a false assurance it was checked.
Why an off-platform deal costs you more than the commission
The instinctive way to think about leakage is arithmetic: a £35 jacket sold on WhatsApp costs you your percentage of £35. That is the smallest part of it.
What leaves with the deal is every protection you offer both sides. No escrow, so the buyer pays a stranger with nothing between them and a seller who does not post. No dispute process, because you never saw the transaction. No order record, no tracking, no refund route, no review, no evidence of what was agreed.
Then it goes wrong, and it comes back to you anyway: the complaint arrives on your marketplace regardless of where the money moved, because your marketplace is where they met. You take the reputational damage, the support burden and the one-star review for a transaction you earned nothing from. Sellers lose the same way in reverse — no payment protection, and no recourse when a buyer claims an item never arrived.
It compounds, too. A pair who deal off-platform once have no reason to come back through you next time. You do not lose one commission — you lose the relationship, quietly. That is why the filter is worth switching on even if you never enforce it.
Your settings, and what they change
Three checkboxes, in the Messaging & Offers section of WordPress admin → BazaarKit → Settings.
| Setting | What it does | Default |
|---|---|---|
| Let buyers make an offer and negotiate a price | Turns price negotiation on and off. Off means the "Make an offer" button disappears everywhere and no new offer or counter can start — but accepted offers are still honoured at checkout, offers in flight can still be accepted or declined, open offers still expire, and nothing is deleted. | On |
| Screen messages for email addresses, phone numbers, social handles and off-site links | Turns the contact-detail filter on. You are emailed whenever contact details are detected. With this off the filter is entirely dormant. | Off |
| Monitor only — alert me, but never block a message | The tuning mode for the setting above. Detection and alerts run as normal, but nothing is refused. Start here, read a week of alerts, and turn it off only once you are satisfied real messages are not being caught. | Off |
Read those two defaults together. The filter is off and monitor-only is also off, so ticking the filter alone starts blocking messages immediately. To measure before you enforce, tick both boxes.
What you need to change in WooCommerce
Nothing. No shipping zones, payment settings, page assignments or product options. The inbox adds itself as a dashboard tab, the product-page buttons hook onto the standard WooCommerce single-product template, and the agreed price is applied through WooCommerce's own basket calculation.
Worth a glance elsewhere: your admin email address (Settings → General), because that is where filter alerts go; your outgoing mail, since notifications use WordPress's own mail function; and the fact that messaging and offers need an account, so guests are sent to log in first. The module itself is switched on once from BazaarKit → Add-ons.
How to check it is working
- Open a vendor's product while logged in as a different account. You should see Message seller beneath the price and Make an offer beside the add-to-cart button.
- Send a short message, then open
/dashboard/messages/. The thread should be there with the item attached to it. - Attach an image and send it. Open it in a new tab: the address should be a long signed link, not a plain file in your uploads folder.
- Make an offer below the listed price, then log in as the vendor. The offer card should show accept, counter and decline.
- Accept it, add the item to the basket as the buyer, and check the total shows the agreed price rather than the listed one.
- Tick both filter boxes and message yourself an obvious email address. You should get an alert saying it was detected and allowed. Untick monitor-only, send it again, and it should be refused.
The live demo has all of this set up if you would rather poke at a working marketplace than build one.
Troubleshooting
"Make an offer" is missing on a product
Four normal reasons, in rough order of likelihood. Offers are switched off. The item is out of stock, unpurchasable or has no price, so there is nothing to negotiate on. The viewer is the seller of that item. Or nobody is logged in — offers need an account, though guests still see the Message-seller link.
"You already have an offer on this item"
Working as intended: one live offer per person per item, so a second cannot be stacked onto a negotiation already in flight. Once the current offer is answered or expires, the buyer can make a fresh one from inside the thread.
A buyer says the agreed price was not applied at checkout
Check three things. Is there more than one of that item in the basket? An accepted offer covers a single unit. Has it been over 48 hours since the seller accepted? The price lock expires. And is the buyer signed in as the account that made the offer? The price is matched to that person and that item.
The filter is blocking messages that look innocent
Turn monitor only back on immediately — that stops all blocking while leaving alerts running, so you can see what is being caught without refusing anything further. If links to your own site are being flagged, note that both the www and non-www forms of your domain are recognised as yours; other hosts, such as a CDN or a sister site, can be allowed by a developer through a filter hook.
Notification emails are not arriving
Message emails are throttled to one per recipient per thread per ten minutes, so a rapid exchange produces one email rather than fifteen — that is by design. If nothing arrives at all, it is almost always site-wide email delivery rather than this add-on.
Frequently asked questions
Does Dokan have built-in buyer to seller messaging?
Not as a chat. Store Support is ticketing, and the Live Chat module is a paid wrapper around Facebook Messenger or TalkJS. Neither is a threaded buyer↔vendor inbox living on your own site.
Is this a Dokan Live Chat alternative? Does it use Facebook Messenger or TalkJS?
It is an alternative, and it uses neither. No third-party chat provider, no per-seat fee — messages, offers and attachments stay in your own WordPress database.
Where do the messages live — do they leave my site?
They stay on your site. Conversations, messages and offers are rows in your own database, and attachments are files in your own uploads folder. The add-on uses no external services.
Can I stop buyers and sellers swapping phone numbers and dealing off-platform?
That is what the contact-detail filter is for. It screens message text for email addresses, phone numbers, social handles and off-site links, emails you on detection, and can block the message. It is off by default.
Will the contact filter block legitimate messages?
It is built to err the other way. A long number on its own is reported but allowed, because tracking codes and size lists look the same; it blocks only with corroboration, such as the message asking to be telephoned.
How do buyers make an offer, and can a vendor counter?
A buyer presses "Make an offer" on the product page and enters an amount below the listed price and at least half of it. The vendor can accept, decline or counter, and a counter passes the turn back to the buyer.
How long does an offer last?
An open offer stays live for 48 hours, and every counter restarts that clock. Once accepted, the agreed price is held for a further 48 hours before it lapses.
Can I turn offers off and keep the inbox?
Yes. Untick one box and the "Make an offer" button disappears everywhere, while messaging carries on as before. Accepted offers are still honoured at checkout and nothing is deleted.
Are image attachments in messages private?
Yes. They live in a deny-all uploads folder under a randomised filename, are kept out of the WordPress media API, and are served only through a signed, expiring link generated inside the conversation.
Do I need Dokan Pro for this?
No. It works on Dokan Lite alongside the free BazaarKit core. If you already own Pro the two coexist, but nothing here depends on it.
Where to go next
Give your buyers somewhere to ask.
A first-party inbox, offers that check out at the agreed price, and a filter that keeps the deal on your marketplace — £7 a month, cancel anytime, on top of the free BazaarKit core. See all documentation, or how it compares to Dokan Pro.
See pricing Try the live demo