[{"data":1,"prerenderedAt":758},["ShallowReactive",2],{"blog-llm-rfq-quote-automation-en":3},{"slug":4,"published":5,"minutes":6,"category":7,"tags":8,"keywords":14,"about":25,"sources":35,"cover":72,"og":73,"expertise":74,"locales":75,"lang":76,"title":79,"description":80,"coverAlt":81,"metaTitle":82,"takeaways":83,"faq":89,"toc":105,"blocks":136,"others":485},"llm-rfq-quote-automation","2026-10-14",8,"web",[9,10,11,12,13],"RFQ","Quote automation","Document AI","Product matching","Human review",[15,16,17,18,19,20,21,22,23,24],"RFQ automation","automated quote generation","quote automation LLM","request for quote parsing","part number matching","B2B quote automation software","AI quote generation distribution","human in the loop document review","PDF RFQ extraction","semantic product matching",[26,29,32],{"name":27,"url":28},"Request for quotation","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FRequest_for_quotation",{"name":30,"url":31},"Optical character recognition","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FOptical_character_recognition",{"name":33,"url":34},"Large language model","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLarge_language_model",[36,39,42,45,48,51,54,57,60,63,66,69],{"title":37,"url":38},"Harvard Business Review: The Short Life of Online Sales Leads (March 2011)","https:\u002F\u002Fhbr.org\u002F2011\u002F03\u002Fthe-short-life-of-online-sales-leads",{"title":40,"url":41},"Mistral AI: OCR 4.1 model card","https:\u002F\u002Fdocs.mistral.ai\u002Fmodels\u002Focr-4-1",{"title":43,"url":44},"Mistral AI: models overview and deprecations","https:\u002F\u002Fdocs.mistral.ai\u002Fgetting-started\u002Fmodels\u002Fmodels_overview\u002F",{"title":46,"url":47},"Google Cloud: Document AI pricing","https:\u002F\u002Fcloud.google.com\u002Fdocument-ai\u002Fpricing",{"title":49,"url":50},"Google Cloud: Document AI deprecations","https:\u002F\u002Fcloud.google.com\u002Fdocument-ai\u002Fdocs\u002Fdeprecation",{"title":52,"url":53},"Amazon Textract pricing","https:\u002F\u002Faws.amazon.com\u002Ftextract\u002Fpricing\u002F",{"title":55,"url":56},"Microsoft Learn: Azure OpenAI structured outputs","https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fai-foundry\u002Fopenai\u002Fhow-to\u002Fstructured-outputs",{"title":58,"url":59},"Tian et al.: Just Ask for Calibration (EMNLP 2023)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2305.14975",{"title":61,"url":62},"Peppol BIS Upgrade 3: ordering profiles and code lists","https:\u002F\u002Fdocs.peppol.eu\u002Fpoacc\u002Fupgrade-3\u002F",{"title":64,"url":65},"ETIM International: model releases","https:\u002F\u002Fwww.etim-international.com\u002Fdownloads\u002F?_sft_downloadcategory=model-releases",{"title":67,"url":68},"ECLASS: classification standard","https:\u002F\u002Fwww.eclass.eu\u002F",{"title":70,"url":71},"O*NET OnLine: Order Clerks (43-4151.00)","https:\u002F\u002Fwww.onetonline.org\u002Flink\u002Fsummary\u002F43-4151.00","\u002Fimages\u002Fblog\u002Fllm-rfq-quote-automation\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fllm-rfq-quote-automation\u002Fog.jpg","b2b-ecommerce-developer",[76,77,78],"en","de","hu","RFQ automation with LLMs: parsing, part matching and human review","How to automate RFQ handling with LLMs: document intake, line extraction, part-number matching, contract pricing and a review queue that stays fast.","A sheet leaves an envelope and becomes a sealed document via a small gear.","RFQ automation with LLMs · Balázs Csorba",[84,85,86,87,88],"RFQ automation should prepare the quote, not send it: the pipeline turns one inbound document into proposed lines with evidence, and a human approves before anything leaves the company.","Match part numbers through a waterfall: exact identifiers first, then a customer cross-reference table, then semantic search, and never give a semantic hit the confidence of an exact one.","The model never produces a price; lines are priced by the same contract and ERP path as the shop, or marked as price on request.","Strict structured-output modes support only a subset of JSON Schema, so unit, quantity and part-number checks belong in code after extraction.","No published study links RFQ response time to win rate; build the business case from your own touch minutes per RFQ and the published per-page extraction prices.",[90,93,96,99,102],{"q":91,"a":92},"What is RFQ automation?","RFQ automation turns an inbound request for quotation, such as an email, PDF or spreadsheet, into a draft quote: it extracts the requested lines, matches them to your articles, prices them from contracts or the ERP, and routes each line to a reviewer with its confidence and evidence. A person approves and sends the quote.",{"q":94,"a":95},"Can an LLM generate prices for a quote?","It should not. Prices must come from the same source as the shop or ERP: contract prices, tiers and validity for that customer. If no price can be resolved, the line is marked price on request, which is a normal business state, not an error the model should fill in.",{"q":97,"a":98},"How accurate is AI part-number matching?","It depends on the identifiers in the document. Lines with an exact supplier, manufacturer or known customer part number can be matched reliably and reviewed lightly. Description-only lines need semantic or attribute matching and should always be reviewed. Measure acceptance rates separately per match path on your own historical RFQs.",{"q":100,"a":101},"What does it cost to extract an RFQ document?","As of October 2026, OCR is cheap compared with staff time: Mistral OCR 4.1 lists $4 per 1,000 pages, Google Document AI OCR $1.50 per 1,000 pages, and Amazon Textract table analysis $0.015 per page. Language model tokens and, above all, review minutes dominate the cost per quote.",{"q":103,"a":104},"Should I use a vendor console for human review of extracted documents?","Be careful. Google deprecated Document AI Human in the Loop in January 2024. A small review queue you own, with per-line accept and correct actions and evidence next to each line, is safer and lets corrections feed your cross-reference table.",[106,109,112,115,118,121,124,127,130,133],{"id":107,"title":108},"what-rfq-automation-actually-changes","What does RFQ automation actually change?",{"id":110,"title":111},"the-pipeline-from-inbox-to-draft-offer","The pipeline from inbox to draft quote",{"id":113,"title":114},"reading-the-rfq-document","How do you read the RFQ document?",{"id":116,"title":117},"matching-lines-to-articles","How do you match RFQ lines to articles?",{"id":119,"title":120},"pricing-the-draft-from-contracts-and-erp","Where do the prices come from?",{"id":122,"title":123},"confidence-review-queues-and-failure-taxonomy","How should the review queue work?",{"id":125,"title":126},"what-it-is-worth","What is RFQ automation worth?",{"id":128,"title":129},"when-not-to-use-it","When is RFQ automation not worth it?",{"id":131,"title":132},"rfq-automation-checklist","A checklist for an RFQ automation pilot",{"id":134,"title":135},"sources","Sources",[137,144,147,150,153,156,157,160,166,197,198,201,270,285,288,289,292,296,332,334,335,338,345,346,349,375,386,393,394,397,404,411,413,416,417,420,421,439,446,447],{"type":138,"content":139},"paragraph",[140,143],{"tag":141,"children":142},"strong",[15]," with large language models means turning an inbound request for quotation, an email body, a PDF, a spreadsheet or a portal export, into a draft quote: extracted lines, matched articles, prices from your contracts, and a per-line confidence that tells a reviewer where to look. The reviewer approves, and only then does a quote leave the company.",{"type":138,"content":145},[146],"This article covers the pipeline stage by stage, how to read messy RFQ documents, how to match lines to articles without trusting the model too much, how pricing stays deterministic, how to design the review queue, and what the business case can honestly claim. The quote as a versioned workflow object and the pricing engine itself are separate topics; this post consumes both.",{"type":148,"level":149,"id":107,"text":108},"heading",2,{"type":138,"content":151},[152],"It automates preparation, never the offer. Retyping positions, looking up part numbers and checking contract prices are what take an inside-sales team’s time, and those are the steps a pipeline can do in seconds. Deciding what to offer stays with a person.",{"type":138,"content":154},[155],"The failure costs are asymmetric. An unmatched line that a reviewer resolves in twenty seconds is normal operation. A wrong article at the wrong price on a sent quote is the only failure that really matters, because the customer may accept it. Design everything around that asymmetry. Also be clear about what automation does not fix: missing contract prices, articles you do not sell, and bad customer master data stay problems after the pipeline exists.",{"type":148,"level":149,"id":110,"text":111},{"type":138,"content":158},[159],"The pipeline has six stages, and each produces an artifact that a reviewer can inspect: the original document, parsed text with positions, a typed array of lines, a match per line with its path, a price per line with its source, and the draft quote with a confidence per line.",{"type":161,"src":162,"alt":163,"wide":164,"caption":165},"image","\u002Fimages\u002Fblog\u002Fllm-rfq-quote-automation\u002Fdiagram-7.webp","RFQ automation pipeline Six stages from left to right: intake of email, PDF or spreadsheet; parsing into text and tables with positions; extraction of typed lines; matching through exact identifiers, cross-references and semantic search; pricing from contracts and the ERP; and a human review gate before the quote is sent.",true,"The RFQ pipeline: every stage produces an artifact a reviewer can inspect, and only the last, human stage can send a quote.",{"type":138,"content":167},[168,169,173,174,177,178,181,182,185,186,190,191,196],"Extraction into a typed array is where structured outputs help, and also where they stop. Strict modes accept only a subset of JSON Schema. Azure OpenAI’s documentation, for example, requires every field to be required, needs ",{"tag":170,"children":171},"code",[172],"additionalProperties: false",", does not support ",{"tag":170,"children":175},[176],"pattern",", ",{"tag":170,"children":179},[180],"minimum"," or ",{"tag":170,"children":183},[184],"maxItems",", and caps schemas at 100 properties and five nesting levels (",{"tag":187,"href":56,"children":188},"a",[189],"Microsoft Learn","). So quantity ranges, unit-of-measure enums and part-number formats are validated in code after extraction, as described in ",{"tag":192,"to":193,"children":194},"link","\u002Fblog\u002Fstructured-outputs-json-schema-llm",[195],"structured outputs with JSON Schema",".",{"type":148,"level":149,"id":113,"text":114},{"type":138,"content":199},[200],"Route each document by what it is, because the cheapest reliable route differs per format. What actually arrives is mixed: email bodies with a table pasted as text, Excel sheets, scanned PDFs of an old spreadsheet, portal exports, and occasionally a structured order message.",{"type":202,"head":203,"rows":214},"table",[204,206,208,210,212],[205],"Route",[207],"Typical input",[209],"Cost anchor (Oct 2026)",[211],"Typical failure",[213],"Use when",[215,226,237,248,259],[216,218,220,222,224],[217],"OCR only",[219],"clean scans, one table",[221],"Document AI OCR $1.50 per 1,000 pages; Textract $0.0015 per page",[223],"columns merged, rows split",[225],"text is all you need",[227,229,231,233,235],[228],"OCR with tables",[230],"scanned spreadsheets",[232],"Textract tables $0.015 per page",[234],"multi-page tables, header lost",[236],"tables dominate",[238,240,242,244,246],[239],"Vision LLM with boxes",[241],"mixed layouts, notes",[243],"Mistral OCR 4.1 $4 per 1,000 pages, $5 annotated",[245],"plausible but invented values",[247],"layout varies per customer",[249,251,253,255,257],[250],"Native text",[252],"email body, CSV, XLSX",[254],"no OCR cost",[256],"units and decimals misread",[258],"always, first",[260,262,264,266,268],[261],"Structured order",[263],"EDIFACT, Peppol",[265],"parsing only",[267],"codelist mismatch",[269],"the customer can send it",{"type":138,"content":271},[272,273,276,277,280,281,196],"Peppol’s ordering documents are a useful target shape even when nobody sends them: their code lists distinguish buyer, seller and manufacturer item identifiers, use UN\u002FECE Recommendation 20 units of measure, and ISO 4217 currencies (",{"tag":187,"href":62,"children":274},[275],"Peppol BIS","). Normalize every route toward that shape. Prices from the table come from Google, AWS and Mistral pricing pages as of October 2026, and the models churn: Mistral deprecated OCR 4.0 on 29 September 2026 and retired it a day later (",{"tag":187,"href":44,"children":278},[279],"Mistral","), so keep the extraction layer swappable. The general parsing trade-offs are in ",{"tag":192,"to":282,"children":283},"\u002Fblog\u002Fpdf-document-parsing-for-rag",[284],"PDF parsing for RAG",{"type":138,"content":286},[287],"German RFQs add their own long tail: “Stk.” and “VE” as units, “Lfd. Nr.” as a position column, decimal commas, and compound nouns in descriptions. That is a normalization problem, not a translation problem, and it belongs in a small, tested set of rules rather than in the prompt.",{"type":148,"level":149,"id":116,"text":117},{"type":138,"content":290},[291],"Use a waterfall: exact identifiers first, then a customer cross-reference table, then semantic search, and record which path produced each match. The path decides how much review the line needs, so a semantic hit must never carry the confidence of an exact one.",{"type":161,"src":293,"alt":294,"wide":164,"caption":295},"\u002Fimages\u002Fblog\u002Fllm-rfq-quote-automation\u002Fdiagram-16.webp","Part-number match waterfall Three match paths from left to right. An exact identifier hit is eligible for auto-accept. If there is no hit, a customer cross-reference lookup follows and needs light review. If that fails too, semantic or attribute search proposes candidates that always need review with an evidence panel. A human correction on the semantic path writes a new cross-reference row, so future lines move left to the cheaper path.","The match waterfall: cheap, precise paths first; every human correction on the semantic path becomes a cross-reference row, so the share of lightly reviewed lines grows over time.",{"type":297,"ordered":298,"items":299},"list",false,[300,305,310,320],[301,304],{"tag":141,"children":302},[303],"Normalize per identifier type."," Buyer, supplier and manufacturer part numbers are different identifier types; normalize case, spaces and separators per type, and look them up in a dedicated identifier index, not in the shop’s product search.",[306,309],{"tag":141,"children":307},[308],"Treat cross-references as an asset."," A table that maps a customer’s own article number to your SKU grows from every human correction, and over time it moves lines from the expensive path to the cheap one.",[311,314,315,319],{"tag":141,"children":312},[313],"Semantic search proposes, it does not decide."," Hybrid retrieval with reranking, as in ",{"tag":192,"to":316,"children":317},"\u002Fblog\u002Fsemantic-product-search-b2b",[318],"semantic product search for B2B",", produces a candidate list for the reviewer, not an answer.",[321,324,325,177,328,331],{"tag":141,"children":322},[323],"Description-only catalogs need attributes."," If neither side has stable identifiers, match on classified attributes, for example ETIM, whose newest model release is 10.0, or ECLASS, currently at Release 16.0 (",{"tag":187,"href":65,"children":326},[327],"ETIM",{"tag":187,"href":68,"children":329},[330],"ECLASS","), and expect low auto-accept rates.",{"type":170,"code":333},"\u002F\u002F Match waterfall (sketch): exact identifiers first, semantic last, never the same confidence\ntype MatchPath = 'exact' | 'xref' | 'semantic'\ntype Match = { sku: string | null; path: MatchPath; review: 'optional' | 'light' | 'required'; evidence: unknown }\n\n\u002F\u002F normalize(id) applies per-type rules: case, spaces and separators for supplier numbers, etc.\n\nasync function matchLine(line: RfqLine, customer: string): Promise\u003CMatch> {\n  for (const id of line.identifiers) {                      \u002F\u002F buyer, supplier, manufacturer numbers\n    const hit = await idIndex.get(id.type, normalize(id))      \u002F\u002F dedicated identifier index, not the shop search\n    if (hit) return { sku: hit.sku, path: 'exact', review: 'optional', evidence: id }\n  }\n  const xref = line.buyerPartNo && await crossRef.get(customer, line.buyerPartNo)\n  if (xref) return { sku: xref.sku, path: 'xref', review: 'light', evidence: xref }\n\n  const candidates = await hybridSearch(line.description, { rerank: true, k: 5 })\n  return { sku: candidates[0]?.sku ?? null, path: 'semantic', review: 'required', evidence: candidates }\n}",{"type":148,"level":149,"id":119,"text":120},{"type":138,"content":336},[337],"From the same path the shop uses, never from the model. Each matched line is priced by the pricing service or the ERP with the customer’s contract prices, tiers, currency and validity, and the draft stores the source and timestamp of every price.",{"type":138,"content":339},[340,341,196],"A line has two legitimate states: priced, with source, or price on request. The second is a normal business state and should look like one in the review queue. Surface the edge cases explicitly: contract prices that expire before the quote’s validity ends, minimum order quantities and packaging units that change the requested quantity, items that are not available to promise, and lines that match a cross-reference but no longer a sellable article. Configured products are a rules problem; hand them to the configurator, as described in ",{"tag":192,"to":342,"children":343},"\u002Fblog\u002Fheadless-product-configurator-b2b",[344],"headless product configurators for B2B",{"type":148,"level":149,"id":122,"text":123},{"type":138,"content":347},[348],"Treat the review queue as the product, because reviewer minutes per line are the main cost. Sort failures into two groups. Dangerous ones: wrong article, wrong price, an invented line. Harmless ones: an unmatched line, an ambiguous unit, a missing delivery date, a typo in the customer’s own part number. The queue exists to make the first group impossible to send and the second group fast to fix.",{"type":297,"ordered":298,"items":350},[351,360,365,370],[352,355,356,359],{"tag":141,"children":353},[354],"Confidence from signals, not from the model alone."," Combine the match path, the identifier check and the retrieval score. Verbalized model confidence is useful for ranking; Tian et al. found it better calibrated than token probabilities for RLHF models (",{"tag":187,"href":59,"children":357},[358],"EMNLP 2023","), but it is still not a probability you can threshold blindly.",[361,364],{"tag":141,"children":362},[363],"Evidence next to the line."," Show the source cell from the document, the matched article and the price provenance side by side, so review means checking, not searching.",[366,369],{"tag":141,"children":367},[368],"Keyboard-first, per line."," Accept, correct or reject each line with one key; allow bulk accept only for exact-identifier lines.",[371,374],{"tag":141,"children":372},[373],"Corrections write back."," Every correction on the semantic path becomes a cross-reference row for that customer.",{"type":376,"variant":377,"title":378,"body":379},"callout","warn","Own the review queue",[380],[381,382,385],"Google deprecated Document AI Human in the Loop on 16 January 2024 (",{"tag":187,"href":50,"children":383},[384],"Google Cloud","). A vendor review console can disappear while your process depends on it. A small queue you own, with per-line actions and an audit trail, is a few weeks of work and stays under your control.",{"type":138,"content":387},[388,389,392],"The same idea drives my ",{"tag":170,"children":390},[391],"jev-decide"," skill: each item gets an explicit decision with a confidence, and low confidence goes to a human instead of a global on or off switch for the AI. For the queue, I would also add an end-to-end test with Playwright MCP that loads an anonymized historical RFQ, checks the extracted line count and matches, and asserts that nothing is sent without an explicit click.",{"type":148,"level":149,"id":125,"text":126},{"type":138,"content":395},[396],"It is worth the touch minutes it removes and the response time it shortens, and both have to be measured on your own data. No peer-reviewed or otherwise primary study measuring RFQ response time against win rate was found, and the article will not borrow one.",{"type":138,"content":398},[399,400,403],"The closest published evidence is about sales leads, not RFQs. Harvard Business Review audited 2,241 US companies and found an average response time of 42 hours among those that answered within 30 days; in a second dataset of 1.25 million leads, firms that contacted a lead within an hour were nearly 7 times as likely to qualify it as those waiting an hour longer, and more than 60 times as likely as those waiting 24 hours or more (",{"tag":187,"href":38,"children":401},[402],"HBR, March 2011","). That data is lead-level, mostly B2C and fifteen years old, so it supports the direction, not a number.",{"type":138,"content":405},[406,407,410],"The cost side can be computed. Extraction is cheap per page; staff time is not. A reference point for the wage term is the US median wage for order clerks, $22.20 per hour in 2025 according to ",{"tag":187,"href":71,"children":408},[409],"O*NET",", about $0.37 per minute before overhead. Use your own loaded cost:",{"type":170,"code":412},"cost per RFQ = pages × OCR price per page\n             + LLM tokens × token price\n             + review minutes × loaded cost per minute\n\nillustration, not a benchmark (as of October 2026):\n  3 pages × $0.004 (Mistral OCR 4.1)           = $0.012\n  review minutes × $0.37 (US order clerk median wage $22.20\u002Fh, unloaded)\n  → staff time dominates; measure your own minutes before and after",{"type":138,"content":414},[415],"For a head of sales or COO at a distributor, the phrase that matches the need is “reduce quote turnaround time”, and the two headline metrics are review minutes per line and the wrong-match rate that reaches a customer, which the human gate keeps at zero.",{"type":148,"level":149,"id":128,"text":129},{"type":138,"content":418},[419],"Skip it when RFQ volume is small, because the review interface costs more than it saves; when your catalog has no stable identifiers at all; when contract prices are out of reach of any system, because the draft would be guesswork; and in any workflow where a wrong quote would be binding without a person in between.",{"type":148,"level":149,"id":131,"text":132},{"type":297,"ordered":164,"items":422},[423,425,427,429,431,433,435,437],[424],"Build a golden set of 50 to 200 historical RFQs with known-correct lines, articles and prices.",[426],"Measure touch minutes per RFQ before the pilot.",[428],"Report acceptance per line, split by match path: exact, cross-reference, semantic.",[430],"Validate units, quantities and part-number formats in code after extraction.",[432],"Price only through the contract and ERP path; mark the rest price on request.",[434],"Make every sent quote traceable to the source document region and the price record.",[436],"Feed corrections back into the cross-reference table.",[438],"Pin the extraction model version and re-run the golden set on every swap.",{"type":138,"content":440},[441,442,196],"After more than ten years of B2B commerce and PIM work, my experience is that the PIM side is usually clean and the incoming customer documents are not, so I would spend more of a pilot on intake and the review queue than on the model. A fixed-scope pilot on a few hundred historical RFQs is the honest way to find the numbers; if you want to scope one, see my ",{"tag":192,"to":443,"children":444},"\u002Fexpertise\u002Fb2b-ecommerce-developer",[445],"B2B e-commerce work",{"type":148,"level":149,"id":134,"text":135},{"type":297,"ordered":164,"items":448},[449,452,455,458,461,464,467,470,473,476,479,482],[450],{"tag":187,"href":38,"children":451},[37],[453],{"tag":187,"href":41,"children":454},[40],[456],{"tag":187,"href":44,"children":457},[43],[459],{"tag":187,"href":47,"children":460},[46],[462],{"tag":187,"href":50,"children":463},[49],[465],{"tag":187,"href":53,"children":466},[52],[468],{"tag":187,"href":56,"children":469},[55],[471],{"tag":187,"href":59,"children":472},[58],[474],{"tag":187,"href":62,"children":475},[61],[477],{"tag":187,"href":65,"children":478},[64],[480],{"tag":187,"href":68,"children":481},[67],[483],{"tag":187,"href":71,"children":484},[70],[486,560,616,690],{"slug":487,"published":488,"minutes":489,"category":7,"tags":490,"keywords":496,"about":508,"sources":517,"cover":554,"og":555,"expertise":74,"locales":556,"lang":76,"title":557,"description":558,"coverAlt":559},"schema-org-structured-data-b2b-shop","2026-10-17",10,[491,492,493,494,495],"Schema.org","Structured data","B2B e-commerce","Technical SEO","Nuxt",[497,498,499,500,501,502,503,504,505,506,507],"schema.org b2b shop","product structured data b2b","merchant listing structured data","product snippet vs merchant listing","unitpricespecification referencequantity","productgroup variants structured data","organization schema vatid","b2b prices behind login seo","json-ld nuxt schema org","merchant return policy structured data","mpn gtin structured data",[509,511,514],{"name":491,"url":510},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSchema.org",{"name":512,"url":513},"JSON-LD","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FJSON-LD",{"name":515,"url":516},"Business-to-business","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBusiness-to-business",[518,521,524,527,530,533,536,539,542,545,548,551],{"title":519,"url":520},"Google Search Central: Introduction to Product structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fproduct",{"title":522,"url":523},"Google Search Central: Merchant listing (Product, Offer) structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fmerchant-listing",{"title":525,"url":526},"Google Search Central: Product snippet structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fproduct-snippet",{"title":528,"url":529},"Google Search Central: Product variant structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fproduct-variants",{"title":531,"url":532},"Google Search Central: Organization structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Forganization",{"title":534,"url":535},"Google Search Central: Merchant return policy structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Freturn-policy",{"title":537,"url":538},"Google Search Central: General structured data guidelines","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fsd-policies",{"title":540,"url":541},"Google Search Central: Generate structured data with JavaScript","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fgenerate-structured-data-with-javascript",{"title":543,"url":544},"Schema.org: Offer","https:\u002F\u002Fschema.org\u002FOffer",{"title":546,"url":547},"Schema.org: UnitPriceSpecification","https:\u002F\u002Fschema.org\u002FUnitPriceSpecification",{"title":549,"url":550},"Unhead: Product schema (defineProduct)","https:\u002F\u002Funhead.unjs.io\u002Fdocs\u002Fschema-org\u002Fapi\u002Fschema\u002Fproduct",{"title":552,"url":553},"Nuxt SEO: Schema.org identity setup","https:\u002F\u002Fnuxtseo.com\u002Fdocs\u002Fschema-org\u002Fguides\u002Fsetup-identity","\u002Fimages\u002Fblog\u002Fschema-org-structured-data-b2b-shop\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fschema-org-structured-data-b2b-shop\u002Fog.jpg",[76,77,78],"Schema.org structured data for B2B shops: prices behind logins, units and variants","Product markup for B2B shops: snippet or merchant listing, which price to publish, part numbers, unit pricing, variants, Organization and SSR in Nuxt.","A product rectangle with a framed outline and a small price slot hidden behind a low wall.",{"slug":561,"published":488,"minutes":562,"category":7,"tags":563,"keywords":568,"about":580,"sources":588,"cover":610,"og":611,"expertise":74,"locales":612,"lang":76,"title":613,"description":614,"coverAlt":615},"ai-assistant-b2b-shop-customer-support",9,[493,564,565,566,567],"AI assistant","Customer support","LLM agents","EU AI Act",[569,570,571,572,573,574,575,576,577,578,579],"ai assistant b2b shop","ai customer support b2b ecommerce","llm chatbot order status","ai agent customer service tools","chatbot liability air canada","klarna ai assistant results","human handoff chatbot design","eu ai act chatbot disclosure","owasp excessive agency","ai support resolution rate","b2b customer portal chatbot",[581,584,587],{"name":582,"url":583},"Customer service","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCustomer_service",{"name":585,"url":586},"Chatbot","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FChatbot",{"name":515,"url":516},[589,592,595,598,601,604,607],{"title":590,"url":591},"Klarna: AI assistant handles two-thirds of customer service chats in its first month (press release, 2024)","https:\u002F\u002Fwww.klarna.com\u002Finternational\u002Fpress\u002Fklarna-ai-assistant-handles-two-thirds-of-customer-service-chats-in-its-first-month\u002F",{"title":593,"url":594},"Entrepreneur: Klarna is hiring customer service agents again, according to its CEO (May 2025)","https:\u002F\u002Fwww.entrepreneur.com\u002Fbusiness-news\u002Fklarna-ceo-reverses-course-by-hiring-more-humans-not-ai\u002F491396",{"title":596,"url":597},"ABA Business Law Today: BC tribunal confirms companies remain liable for information provided by AI chatbot","https:\u002F\u002Fwww.americanbar.org\u002Fgroups\u002Fbusiness_law\u002Fresources\u002Fbusiness-law-today\u002F2024-february\u002Fbc-tribunal-confirms-companies-remain-liable-information-provided-ai-chatbot\u002F",{"title":599,"url":600},"OWASP GenAI Security Project: LLM06:2025 Excessive Agency","https:\u002F\u002Fgenai.owasp.org\u002Fllmrisk\u002Fllm062025-excessive-agency\u002F",{"title":602,"url":603},"OWASP GenAI Security Project: LLM05:2025 Improper Output Handling","https:\u002F\u002Fgenai.owasp.org\u002Fllmrisk\u002Fllm052025-improper-output-handling\u002F",{"title":605,"url":606},"EU AI Act, Article 50: Transparency obligations","https:\u002F\u002Fartificialintelligenceact.eu\u002Farticle\u002F50\u002F",{"title":608,"url":609},"Intercom: Fin pricing and billable outcomes","https:\u002F\u002Ffin.ai\u002Fpricing","\u002Fimages\u002Fblog\u002Fai-assistant-b2b-shop-customer-support\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fai-assistant-b2b-shop-customer-support\u002Fog.jpg",[76,77,78],"An AI assistant for B2B shop support: tools, permissions and the human handoff","How to build an AI support assistant for a B2B shop: which requests to automate, tools that run in the customer context, handoff, AI Act and metrics.","A tall wall with one narrow gap; an arrow passes through it into a boxed enclosure of three squares, and another leads down to a tray.",{"slug":617,"published":488,"minutes":618,"category":7,"tags":619,"keywords":624,"about":636,"sources":646,"cover":683,"og":684,"expertise":685,"locales":686,"lang":76,"title":687,"description":688,"coverAlt":689},"vue-ai-chat-ui-streaming-accessibility",11,[620,495,621,622,623],"Vue","Accessibility","Streaming","AI chat",[625,626,627,628,629,630,631,632,633,634,635],"vue ai chat ui","nuxt llm streaming","sse vs fetch streaming","aria-live streaming text","accessible chat interface","abort fetch stream vue","dompurify markdown llm","role log chat","reduced motion chat ui","wcag 2.2 chat","screen reader streaming",[637,640,643],{"name":638,"url":639},"Web accessibility","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FWeb_accessibility",{"name":641,"url":642},"Server-sent events","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FServer-sent_events",{"name":644,"url":645},"Vue.js","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FVue.js",[647,650,653,656,659,662,665,668,671,674,677,680],{"title":648,"url":649},"MDN: Using server-sent events","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FServer-sent_events\u002FUsing_server-sent_events",{"title":651,"url":652},"MDN: AbortController","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FAbortController",{"title":654,"url":655},"MDN: ReadableStream","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FReadableStream",{"title":657,"url":658},"MDN: TextDecoderStream","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FTextDecoderStream",{"title":660,"url":661},"MDN: ARIA log role","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAccessibility\u002FARIA\u002FReference\u002FRoles\u002Flog_role",{"title":663,"url":664},"W3C: Understanding SC 4.1.3 Status Messages","https:\u002F\u002Fwww.w3.org\u002FWAI\u002FWCAG22\u002FUnderstanding\u002Fstatus-messages.html",{"title":666,"url":667},"W3C WAI: What's new in WCAG 2.2","https:\u002F\u002Fwww.w3.org\u002FWAI\u002Fstandards-guidelines\u002Fwcag\u002Fnew-in-22\u002F",{"title":669,"url":670},"MDN: prefers-reduced-motion","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FCSS\u002F@media\u002Fprefers-reduced-motion",{"title":672,"url":673},"DOMPurify README","https:\u002F\u002Fgithub.com\u002Fcure53\u002FDOMPurify",{"title":675,"url":676},"markdown-it README","https:\u002F\u002Fgithub.com\u002Fmarkdown-it\u002Fmarkdown-it",{"title":678,"url":679},"AI SDK docs: useChat","https:\u002F\u002Fai-sdk.dev\u002Fdocs\u002Fai-sdk-ui\u002Fchatbot",{"title":681,"url":682},"Vue docs: nextTick","https:\u002F\u002Fvuejs.org\u002Fapi\u002Fgeneral.html#nexttick","\u002Fimages\u002Fblog\u002Fvue-ai-chat-ui-streaming-accessibility\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fvue-ai-chat-ui-streaming-accessibility\u002Fog.jpg","vue-nuxt-developer",[76,77,78],"Streaming AI chat in Vue and Nuxt: accessible by design","How to build a Vue or Nuxt AI chat UI: fetch streams, abort and retry, safe markdown rendering, aria-live announcements, keyboard support and reduced motion.","A message card with a careful caret, a dotted line opening into ripples and a check.",{"slug":691,"published":488,"minutes":562,"category":7,"tags":692,"keywords":697,"about":709,"sources":719,"cover":752,"og":753,"expertise":685,"locales":754,"lang":76,"title":755,"description":756,"coverAlt":757},"llm-translation-pipeline-i18n",[693,694,695,620,696],"Translation","i18n","LLM","Localization",[698,699,700,701,702,703,704,705,706,707,708],"llm translation pipeline","icu messageformat placeholders","vue i18n llm translation","translation memory llm","glossary enforcement translation","german informal sie du","hungarian translation quality llm","structured output json translation","machine translation post-editing","locale file validation","cldr plural categories",[710,713,716],{"name":711,"url":712},"Internationalization and localization","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FInternationalization_and_localization",{"name":714,"url":715},"ICU MessageFormat","https:\u002F\u002Funicode-org.github.io\u002Ficu\u002Fuserguide\u002Fformat_parse\u002Fmessages\u002F",{"name":717,"url":718},"Vue I18n","https:\u002F\u002Fvue-i18n.intlify.dev\u002F",[720,722,725,728,731,734,737,740,743,746,749],{"title":721,"url":715},"Unicode ICU User Guide: Formatting Messages",{"title":723,"url":724},"Vue I18n: Message Format Syntax","https:\u002F\u002Fvue-i18n.intlify.dev\u002Fguide\u002Fessentials\u002Fsyntax",{"title":726,"url":727},"Nuxt i18n: Getting started","https:\u002F\u002Fi18n.nuxtjs.org\u002Fdocs\u002Fgetting-started",{"title":729,"url":730},"Unicode CLDR: Plural rules","https:\u002F\u002Fcldr.unicode.org\u002Findex\u002Fcldr-spec\u002Fplural-rules",{"title":732,"url":733},"OpenAI: Structured outputs","https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Fstructured-outputs",{"title":735,"url":736},"DeepL API: Glossaries","https:\u002F\u002Fdevelopers.deepl.com\u002Fdocs\u002Fapi-reference\u002Fglossaries",{"title":738,"url":739},"W3C: Localization vs. internationalization","https:\u002F\u002Fwww.w3.org\u002FInternational\u002Fquestions\u002Fqa-i18n",{"title":741,"url":742},"GNU gettext manual","https:\u002F\u002Fwww.gnu.org\u002Fsoftware\u002Fgettext\u002Fmanual\u002Fgettext.html",{"title":744,"url":745},"RFC 5646: Tags for Identifying Languages","https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc5646",{"title":747,"url":748},"Rat für deutsche Rechtschreibung","https:\u002F\u002Fwww.rechtschreibrat.com\u002F",{"title":750,"url":751},"Microsoft Writing Style Guide","https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fstyle-guide\u002Fwelcome\u002F","\u002Fimages\u002Fblog\u002Fllm-translation-pipeline-i18n\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fllm-translation-pipeline-i18n\u002Fog.jpg",[76,77,78],"An LLM translation pipeline for i18n: glossary, placeholders and review","How to translate product and website strings with LLMs without breaking placeholders, plurals or tone: glossary, ICU messages, QA checks and review gates.","Three source cards, one translated card with a glossary ribbon, then a checked clipboard.",1792337027038]