Supplier quote request (RFQ) sheet: the sales or export inbox each supplier publishes, a chase tracker and a landed-cost comparison in one Google Sheet
What you get: one Google Sheet with two working tabs. The rfq tab has one row per supplier you want a quote from (manufacturers, wholesalers, packaging or print suppliers). It shows the sales, export or orders inbox the supplier publishes on its own website, a general inbox as a fallback, a next step when none is found, the date you asked, a chase date and a do-not-contact column. The quotes tab turns every reply into a landed cost per unit in your own currency, checks the minimum order quantity (MOQ), ranks the suppliers that qualify and gives an order-by date. Formulas are below. The example rows use made-up .example suppliers and made-up numbers.
The finished sheet
rfq tab (example rows are made up)
| Domain | Status | Quote inbox | Fallback | Named inboxes dropped | Next step | Asked on | Chase on | Quote in? | Send? |
|---|---|---|---|---|---|---|---|---|---|
| alpha-moulds.example | ok | export@alpha-moulds.example | 0 | Send RFQ to quote inbox | 26 Oct 2026 | 29 Oct 2026 | Yes | Done | |
| beta-plastics.example | ok | sales@beta-plastics.example | 1 | Send RFQ to quote inbox | 26 Oct 2026 | 29 Oct 2026 | Yes | Done | |
| gamma-pack.example | ok | info@gamma-pack.example | 0 | Use general inbox and ask who handles quotes | 26 Oct 2026 | 29 Oct 2026 | Yes | Done | |
| delta-print.example | ok | 2 | Site lists named inboxes: read its contact page | Ready | |||||
| epsilon-tex.example | blocked-by-terms | Skipped: use the site's contact or quote form | Ready |
quotes tab (example rows are made up; your order is 500 units, your currency INR)
| Supplier | Cur. | Unit price | MOQ | Order qty | Shipping for the order | Duty % (your figure) | FX to INR | Lead time (days) | Landed per unit (INR) | MOQ ok? | Rank | Order by |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| alpha-moulds.example | USD | 2.10 | 500 | 500 | 180 | 10% | 84 | 35 | 227.30 | Yes | 2 | 16 Oct 2026 (too late) |
| beta-plastics.example | USD | 1.95 | 1000 | 500 | 150 | 10% | 84 | 30 | 207.90 | No: order 1000+ | 21 Oct 2026 | |
| gamma-pack.example | INR | 205 | 300 | 500 | 2500 | 0% | 1 | 12 | 210.00 | Yes | 1 | 8 Nov 2026 |
Read it like this: the lowest unit price (beta-plastics) does not qualify at your quantity, and once shipping and duty are added the local supplier (gamma-pack) beats the import quote and is the only qualifying supplier that can still deliver by 20 November. That is the decision the sheet is built to show in one glance.
Who this is for
- Small brands and online shops sourcing a product, packaging, labels or print run from 10 to 50 possible suppliers, and wanting the inbox each supplier itself publishes for sales or export enquiries.
- Buyers and procurement staff at small firms who must show three or more comparable quotes before ordering.
- Anyone who already has a list of supplier websites (from a trade directory, a trade fair or a search) and wants the contact column filled in one run, then a fair like-for-like comparison.
Step 1: list the suppliers in a tab named sites
| Column | What to put |
|---|---|
| A Supplier | Name, for example "Alpha Moulds" |
| B Website | The homepage, for example https://www.alpha-moulds.example |
| C Country | Where it ships from. You need this for shipping, duty and currency in Step 5. |
| D Item | What you want quoted, in the same words for every supplier, so the quotes compare like for like. |
Step 2: run the contact scraper on the websites
Open the website contact scraper on the Apify Store and paste column B into urls (one per line) or startUrls. Set defaultCountry to the country most suppliers are in, so local phone numbers are read correctly. What it does with the default settings, as written in the Actor's input schema and source:
- Reads the homepage plus the most contact-like pages (contact, about, impressum, support):
maxPagesPerSiteis 4 by default. Many manufacturers put the export inbox on an "Export" or "Contact" page deeper in the site, so try 6 if many rows come back empty. - Returns only shared role inboxes.
sales@,export@,exports@,orders@,enquiry@,enquiries@,info@,contact@andhello@are on its role list, and so is a role word plus a country or city tag such assales.uk@. Addresses that identify one person (for examplesales.ravi@) are dropped and only counted inpersonalEmailsDropped(includePersonalEmailsis off). - Checks each inbox's domain can receive mail (
mxValid), and returns phone numbers and company social profiles, including WhatsApp links the site publishes. - Follows robots.txt and reads each site's terms. A site whose terms forbid scraping comes back as
blocked-by-terms; other statuses includeblocked-by-robots,blocked-by-site,rate-limitedandfailed. None of the non-okrows are charged.
Honest limit: in the current version, wholesale@, trade@ and b2b@ are not on the role list, so with the default setting they are dropped and counted, not shown. The sheet turns that count into a "read its contact page" step instead of hiding it.
When the run finishes, export the dataset as CSV, then in your sheet use File, Import, Insert new sheet, and rename it scrape. Nested fields become headers like emails/0/email and emails/0/mxValid, so the formulas below find columns by header name, not by position.
Step 3: build the rfq tab
Create a tab named rfq, put these formulas in row 2 and fill down as many rows as scrape has.
| Col | Header | Formula (row 2) |
|---|---|---|
| A | Domain | =IFERROR(INDEX(scrape!$A2:$ZZ2, MATCH("domain", scrape!$A$1:$ZZ$1, 0)), "") |
| B | Status | =IFERROR(INDEX(scrape!$A2:$ZZ2, MATCH("status", scrape!$A$1:$ZZ$1, 0)), "") |
| C | All inboxes | =IFERROR(TEXTJOIN(", ", TRUE, FILTER(scrape!$A2:$ZZ2, REGEXMATCH(scrape!$A$1:$ZZ$1, "^emails/\d+/email$"))), "") |
| D | Quote inbox | =IFERROR(REGEXEXTRACT(", "&C2, ", ((?:export|exports|sales|orders|enquiry|enquiries)(?:[.\-_][a-z0-9]+)?@[^,]+)"), "") |
| E | Fallback | =IF(D2<>"", "", IFERROR(REGEXEXTRACT(", "&C2, ", ((?:info|contact|hello|office)(?:[.\-_][a-z0-9]+)?@[^,]+)"), "")) |
| F | Named inboxes dropped | =IFERROR(INDEX(scrape!$A2:$ZZ2, MATCH("personalEmailsDropped", scrape!$A$1:$ZZ$1, 0)), 0) |
| G | Next step | =IFS(B2<>"ok", "Skipped ("&B2&"): use the site's contact or quote form", D2<>"", "Send RFQ to quote inbox", N(F2)>0, "Site lists named inboxes: read its contact page", E2<>"", "Use general inbox and ask who handles quotes", TRUE, "No inbox found: use the contact or quote form") |
| H | Bad MX | =IFERROR(SUMPRODUCT(--(UPPER(TO_TEXT(FILTER(scrape!$A2:$ZZ2, REGEXMATCH(scrape!$A$1:$ZZ$1, "^emails/\d+/mxValid$"))))="FALSE")), 0) (above 0: one inbox has no mail server; do not use it) |
| I | Asked on | Type the date you sent the RFQ |
| J | Chase on | =IF(I2="", "", WORKDAY(I2, 3)) |
| K | Quote in? | Type Yes when the quote arrives, then copy it to the quotes tab |
| L | Do not contact | Type Y if the supplier declines or asks you not to write again |
| M | Send? | =IFS(L2="Y", "NO: do not contact", K2="Yes", "Done", I2="", "Ready", TODAY()>=J2, "Chase once", TRUE, "Wait") |
Filter column M and work only the rows that say Ready or Chase once. Write to each supplier one at a time from your normal inbox; one chase is enough.
Step 4: the RFQ email (same questions for everyone)
Asking every supplier the same questions is what makes the quotes comparable. Change only the first line.
Subject: Quote request: [item], [quantity] units, delivery to [city, country] Hello [Supplier] sales team, I am [your name] from [your company], [website]. We are comparing suppliers for [item: material, size, finish, packing]. Please quote: 1. Unit price at [quantity] units, and your price breaks 2. Minimum order quantity (MOQ) 3. Currency, and whether the price includes tax 4. Delivery terms and shipping cost to [city, country] 5. Lead time from order and sample to dispatch 6. Payment terms We plan to decide by [date]. If quotes are handled by someone else, please let me know who. [Your name], [company], [phone] If you would rather not receive requests from us, reply "no".
Step 5: build the quotes tab
Create a tab named quotes with one row per quote received. Type columns A to I from the supplier's reply. Duty and shipping are your own figures: take the duty rate from your country's customs authority for your product code, and the shipping cost from the quote or your forwarder. Put the date you need stock by in cell P1 (for example 20/11/2026, a week before Black Friday on Friday 27 November 2026).
| Col | Header | Formula or entry (row 2) |
|---|---|---|
| A to I | Supplier, Currency, Unit price, MOQ, Order qty, Shipping for the order (in the quote currency), Duty % (as 10%), FX to your currency, Lead time (days) | Typed from the quote |
| J | Landed per unit | =IF(OR(C2="", E2=""), "", ROUND((C2*E2 + F2) * (1 + G2) * H2 / E2, 2)) |
| K | MOQ ok? | =IF(C2="", "", IF(E2>=D2, "Yes", "No: order "&D2&"+")) |
| L | Rank | =IF(K2="Yes", COUNTIFS($K$2:$K, "Yes", $J$2:$J, "<"&J2) + 1, "") |
| M | Order by | =IF(I2="", "", IF($P$1 - I2 < TODAY(), TEXT($P$1 - I2, "d mmm yyyy")&" (too late)", TEXT($P$1 - I2, "d mmm yyyy"))) |
The duty formula above is a simple estimate that applies the rate to goods plus shipping. Your customs authority's rules on the value duty is charged on, and any other import taxes, decide the real figure, so treat column J as a comparison number, not a final cost.
A two-day plan
- Day 1 morning: build the sites tab, run the scraper, fill the rfq tab.
- Day 1 afternoon: send the Ready rows with the same RFQ email; handle the "read its contact page" and form rows by hand.
- Day 1 + 3 working days: chase once where column M says so; mark any "no" as do-not-contact.
- As quotes arrive: copy them to the quotes tab and ask for a sample from the top two ranked suppliers before you order.
Partner programme opening soon
Partner programme opening soon: join the free waitlist. Planned terms are 50% of each referred sale (75% once you have 5+ paying customers), single level, paid through Gumroad only from revenue received.
Sources
- Contact scraper inputs and outputs (
urls,startUrls,defaultCountry,maxPagesPerSitedefault 4,includePersonalEmailsoff,personalEmailsDropped,mxValid, the role-inbox list, statuses such asblocked-by-terms, non-okrows not charged): Apify Store page (Actor input schema, README and source read 21 Oct 2026) - Black Friday 2026 is Friday 27 November (the day after US Thanksgiving, Thursday 26 November).
- Duty rates and customs valuation: your own country's customs authority. This guide gives no duty figures.
Related
- Find public role emails (sales@, press@, support@) on a company website without guessing
- Trade fair exhibitor contact sheet
- Clean an Apify contact CSV into a call sheet
- Turn a contact scrape into a HubSpot or Pipedrive import CSV
Unadhi Guides are free, independent explainers. We correct errors as soon as we find them: write to mininglife7@gmail.com.