[{"data":1,"prerenderedAt":1571},["ShallowReactive",2],{"navigation_docs":3,"-developers-listings-client":178,"-developers-listings-client-surround":1566},[4,25,50,81,112,133,158],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting started",false,"\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-book-open",{"title":16,"path":17,"stem":18,"icon":19},"Concepts","\u002Fgetting-started\u002Fconcepts","1.getting-started\u002F2.concepts","i-lucide-book-a",{"title":21,"path":22,"stem":23,"icon":24},"Quick start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-rocket",{"title":26,"icon":27,"path":28,"stem":29,"children":30,"page":6},"Workspace","i-lucide-users","\u002Fworkspace","2.workspace",[31,36,41,45],{"title":32,"path":33,"stem":34,"icon":35},"Account","\u002Fworkspace\u002Faccount","2.workspace\u002F1.account","i-lucide-circle-user",{"title":37,"path":38,"stem":39,"icon":40},"Teams","\u002Fworkspace\u002Fteams","2.workspace\u002F2.teams","i-lucide-building-2",{"title":42,"path":43,"stem":44,"icon":27},"Members and roles","\u002Fworkspace\u002Fmembers-and-roles","2.workspace\u002F3.members-and-roles",{"title":46,"path":47,"stem":48,"icon":49},"Projects","\u002Fworkspace\u002Fprojects","2.workspace\u002F4.projects","i-lucide-folder-kanban",{"title":51,"icon":52,"path":53,"stem":54,"children":55,"page":6},"Catalogue","i-lucide-package","\u002Fcatalogue","3.catalogue",[56,61,66,71,76],{"title":57,"path":58,"stem":59,"icon":60},"Products","\u002Fcatalogue\u002Fproducts","3.catalogue\u002F1.products","i-lucide-box",{"title":62,"path":63,"stem":64,"icon":65},"Offers","\u002Fcatalogue\u002Foffers","3.catalogue\u002F2.offers","i-lucide-tag",{"title":67,"path":68,"stem":69,"icon":70},"Brands","\u002Fcatalogue\u002Fbrands","3.catalogue\u002F3.brands","i-lucide-badge-check",{"title":72,"path":73,"stem":74,"icon":75},"Merchants","\u002Fcatalogue\u002Fmerchants","3.catalogue\u002F4.merchants","i-lucide-store",{"title":77,"path":78,"stem":79,"icon":80},"Custom attributes","\u002Fcatalogue\u002Fcustom-attributes","3.catalogue\u002F5.custom-attributes","i-lucide-list-plus",{"title":82,"icon":83,"path":84,"stem":85,"children":86,"page":6},"Scraping","i-lucide-scan-search","\u002Fscraping","4.scraping",[87,92,97,102,107],{"title":88,"path":89,"stem":90,"icon":91},"Connect Scrape Admin","\u002Fscraping\u002Fconnect-scrape-admin","4.scraping\u002F1.connect-scrape-admin","i-lucide-plug",{"title":93,"path":94,"stem":95,"icon":96},"Scrape profiles","\u002Fscraping\u002Fscrape-profiles","4.scraping\u002F2.scrape-profiles","i-lucide-scan-text",{"title":98,"path":99,"stem":100,"icon":101},"Schedules and configuration","\u002Fscraping\u002Fschedules-and-configuration","4.scraping\u002F3.schedules-and-configuration","i-lucide-sliders-horizontal",{"title":103,"path":104,"stem":105,"icon":106},"Sync and reconcile","\u002Fscraping\u002Fsync-and-reconcile","4.scraping\u002F4.sync-and-reconcile","i-lucide-refresh-cw",{"title":108,"path":109,"stem":110,"icon":111},"Webhooks","\u002Fscraping\u002Fwebhooks","4.scraping\u002F5.webhooks","i-lucide-webhook",{"title":113,"icon":114,"path":115,"stem":116,"children":117,"page":6},"Growing the catalogue","i-lucide-sprout","\u002Fgrowing-the-catalogue","5.growing-the-catalogue",[118,123,128],{"title":119,"path":120,"stem":121,"icon":122},"Imports","\u002Fgrowing-the-catalogue\u002Fimports","5.growing-the-catalogue\u002F1.imports","i-lucide-import",{"title":124,"path":125,"stem":126,"icon":127},"Repair queues","\u002Fgrowing-the-catalogue\u002Frepair-queues","5.growing-the-catalogue\u002F2.repair-queues","i-lucide-wrench",{"title":129,"path":130,"stem":131,"icon":132},"Wrong URL flow","\u002Fgrowing-the-catalogue\u002Fwrong-url-flow","5.growing-the-catalogue\u002F3.wrong-url-flow","i-lucide-route",{"title":134,"icon":135,"path":136,"stem":137,"children":138,"page":6},"Publishing","i-lucide-globe","\u002Fpublishing","6.publishing",[139,143,148,153],{"title":140,"path":141,"stem":142,"icon":135},"Websites","\u002Fpublishing\u002Fwebsites","6.publishing\u002F1.websites",{"title":144,"path":145,"stem":146,"icon":147},"Website content","\u002Fpublishing\u002Fwebsite-content","6.publishing\u002F2.website-content","i-lucide-languages",{"title":149,"path":150,"stem":151,"icon":152},"SEO templates","\u002Fpublishing\u002Fseo-templates","6.publishing\u002F3.seo-templates","i-lucide-search",{"title":154,"path":155,"stem":156,"icon":157},"Analytics","\u002Fpublishing\u002Fanalytics","6.publishing\u002F4.analytics","i-lucide-chart-line",{"title":159,"icon":160,"path":161,"stem":162,"children":163,"page":6},"Developers","i-lucide-code","\u002Fdevelopers","7.developers",[164,169,173],{"title":165,"path":166,"stem":167,"icon":168},"Public API","\u002Fdevelopers\u002Fpublic-api","7.developers\u002F1.public-api","i-lucide-code-xml",{"title":170,"path":171,"stem":172,"icon":52},"Listings client","\u002Fdevelopers\u002Flistings-client","7.developers\u002F2.listings-client",{"title":174,"path":175,"stem":176,"icon":177},"Click tracking","\u002Fdevelopers\u002Fclick-tracking","7.developers\u002F3.click-tracking","i-lucide-mouse-pointer-click",{"id":179,"title":170,"body":180,"description":1558,"extension":1559,"links":1560,"meta":1561,"navigation":1562,"path":171,"seo":1563,"stem":172,"__hash__":1565},"docs\u002F7.developers\u002F2.listings-client.md",{"type":181,"value":182,"toc":1548},"minimark",[183,196,216,221,303,307,310,473,478,566,570,807,820,1106,1117,1121,1127,1212,1441,1445,1451,1503,1516,1520,1544],[184,185,186,190,191,195],"p",{},[187,188,189],"code",{},"@product-comparison\u002Flistings-client"," is the typed client and contract of the ",[192,193,194],"a",{"href":166},"public API",". It wraps every route, serialises query arguments and rejects with a typed error. The platform imports the same package to validate requests, so the types always match what is served.",[197,198,199,200,203,204,207,208,211,212,215],"note",{},"The package is private to this workspace (",[187,201,202],{},"\"private\": true",", version ",[187,205,206],{},"0.0.1",") and is not published to npm. Consume it as a workspace dependency (",[187,209,210],{},"\"@product-comparison\u002Flistings-client\": \"workspace:*\"",") from an app in this repository, such as ",[187,213,214],{},"apps\u002Ffrontend",".",[217,218,220],"h2",{"id":219},"entry-points","Entry points",[222,223,224,237],"table",{},[225,226,227],"thead",{},[228,229,230,234],"tr",{},[231,232,233],"th",{},"Import",[231,235,236],{},"Contents",[238,239,240,283],"tbody",{},[228,241,242,247],{},[243,244,245],"td",{},[187,246,189],{},[243,248,249,252,253,252,256,259,260,252,263,252,266,252,269,272,273,252,276,252,279,282],{},[187,250,251],{},"createListingsClient",", ",[187,254,255],{},"ListingsError",[187,257,258],{},"isListingsError",", the response types (",[187,261,262],{},"PublicProduct",[187,264,265],{},"PublicOffer",[187,267,268],{},"Page\u003CT>",[187,270,271],{},"Money"," and more), the query types and the outbound helpers (",[187,274,275],{},"isBotUserAgent",[187,277,278],{},"referrerHostOf",[187,280,281],{},"OUTBOUND_REDIRECT_HEADERS",").",[228,284,285,290],{},[243,286,287],{},[187,288,289],{},"@product-comparison\u002Flistings-client\u002Fschema",[243,291,292,293,252,296,299,300,215],{},"The zod schemas of every query string, for example ",[187,294,295],{},"productListQuerySchema",[187,297,298],{},"publicSearchQuerySchema"," and ",[187,301,302],{},"clickReportSchema",[217,304,306],{"id":305},"create-a-client","Create a client",[184,308,309],{},"The token is a server-side secret. Create the client in server code only.",[311,312,317],"pre",{"className":313,"code":314,"language":315,"meta":316,"style":316},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F server\u002Futils\u002Flistings.ts (a Nuxt site)\nimport { createListingsClient } from '@product-comparison\u002Flistings-client'\n\nexport const listings = () => createListingsClient({\n  baseURL: useRuntimeConfig().listingsBaseUrl, \u002F\u002F https:\u002F\u002Fplatform.example\n  token: useRuntimeConfig().listingsToken, \u002F\u002F NUXT_LISTINGS_TOKEN\n  locale: 'nb-NO',\n})\n","ts","",[187,318,319,328,358,365,396,423,445,464],{"__ignoreMap":316},[320,321,324],"span",{"class":322,"line":323},"line",1,[320,325,327],{"class":326},"sHwdD","\u002F\u002F server\u002Futils\u002Flistings.ts (a Nuxt site)\n",[320,329,331,335,339,343,346,349,352,355],{"class":322,"line":330},2,[320,332,334],{"class":333},"s7zQu","import",[320,336,338],{"class":337},"sMK4o"," {",[320,340,342],{"class":341},"sTEyZ"," createListingsClient",[320,344,345],{"class":337}," }",[320,347,348],{"class":333}," from",[320,350,351],{"class":337}," '",[320,353,189],{"class":354},"sfazB",[320,356,357],{"class":337},"'\n",[320,359,361],{"class":322,"line":360},3,[320,362,364],{"emptyLinePlaceholder":363},true,"\n",[320,366,368,371,375,378,381,384,387,390,393],{"class":322,"line":367},4,[320,369,370],{"class":333},"export",[320,372,374],{"class":373},"spNyl"," const",[320,376,377],{"class":341}," listings ",[320,379,380],{"class":337},"=",[320,382,383],{"class":337}," ()",[320,385,386],{"class":373}," =>",[320,388,342],{"class":389},"s2Zo4",[320,391,392],{"class":341},"(",[320,394,395],{"class":337},"{\n",[320,397,399,403,406,409,412,414,417,420],{"class":322,"line":398},5,[320,400,402],{"class":401},"swJcz","  baseURL",[320,404,405],{"class":337},":",[320,407,408],{"class":389}," useRuntimeConfig",[320,410,411],{"class":341},"()",[320,413,215],{"class":337},[320,415,416],{"class":341},"listingsBaseUrl",[320,418,419],{"class":337},",",[320,421,422],{"class":326}," \u002F\u002F https:\u002F\u002Fplatform.example\n",[320,424,426,429,431,433,435,437,440,442],{"class":322,"line":425},6,[320,427,428],{"class":401},"  token",[320,430,405],{"class":337},[320,432,408],{"class":389},[320,434,411],{"class":341},[320,436,215],{"class":337},[320,438,439],{"class":341},"listingsToken",[320,441,419],{"class":337},[320,443,444],{"class":326}," \u002F\u002F NUXT_LISTINGS_TOKEN\n",[320,446,448,451,453,455,458,461],{"class":322,"line":447},7,[320,449,450],{"class":401},"  locale",[320,452,405],{"class":337},[320,454,351],{"class":337},[320,456,457],{"class":354},"nb-NO",[320,459,460],{"class":337},"'",[320,462,463],{"class":337},",\n",[320,465,467,470],{"class":322,"line":466},8,[320,468,469],{"class":337},"}",[320,471,472],{"class":341},")\n",[474,475,477],"h3",{"id":476},"options","Options",[222,479,480,490],{},[225,481,482],{},[228,483,484,487],{},[231,485,486],{},"Option",[231,488,489],{},"Description",[238,491,492,509,523,540,553],{},[228,493,494,499],{},[243,495,496],{},[187,497,498],{},"baseURL",[243,500,501,502,505,506,215],{},"Platform origin, for example ",[187,503,504],{},"https:\u002F\u002Fplatform.example",". The client adds ",[187,507,508],{},"\u002Fapi\u002Fpublic\u002Fv1",[228,510,511,516],{},[243,512,513],{},[187,514,515],{},"token",[243,517,518,519,522],{},"The website's ",[187,520,521],{},"pwt_…"," token.",[228,524,525,530],{},[243,526,527],{},[187,528,529],{},"locale",[243,531,532,533,536,537,539],{},"Default ",[187,534,535],{},"?locale"," for every GET request. A call's own ",[187,538,529],{}," wins.",[228,541,542,547],{},[243,543,544],{},[187,545,546],{},"fetch",[243,548,549,550,552],{},"A custom ",[187,551,546],{},", for tests or Workers service bindings.",[228,554,555,560],{},[243,556,557],{},[187,558,559],{},"userAgent",[243,561,562,563,215],{},"Overrides the default ",[187,564,565],{},"product-comparison\u002Flistings-client",[217,567,569],{"id":568},"methods","Methods",[222,571,572,585],{},[225,573,574],{},[228,575,576,579,582],{},[231,577,578],{},"Method",[231,580,581],{},"Route",[231,583,584],{},"Returns",[238,586,587,604,621,638,655,671,688,705,722,739,756,773,790],{},[228,588,589,594,599],{},[243,590,591],{},[187,592,593],{},"website(query?)",[243,595,596],{},[187,597,598],{},"GET \u002Fwebsite",[243,600,601],{},[187,602,603],{},"PublicWebsite",[228,605,606,611,616],{},[243,607,608],{},[187,609,610],{},"brands.list(query?)",[243,612,613],{},[187,614,615],{},"GET \u002Fbrands",[243,617,618],{},[187,619,620],{},"Page\u003CPublicBrandListItem>",[228,622,623,628,633],{},[243,624,625],{},[187,626,627],{},"brands.get(slug, query?)",[243,629,630],{},[187,631,632],{},"GET \u002Fbrands\u002F:slug",[243,634,635],{},[187,636,637],{},"PublicBrand",[228,639,640,645,650],{},[243,641,642],{},[187,643,644],{},"products.list(query?)",[243,646,647],{},[187,648,649],{},"GET \u002Fproducts",[243,651,652],{},[187,653,654],{},"Page\u003CPublicProductListItem>",[228,656,657,662,667],{},[243,658,659],{},[187,660,661],{},"products.get(slug, query?)",[243,663,664],{},[187,665,666],{},"GET \u002Fproducts\u002F:slug",[243,668,669],{},[187,670,262],{},[228,672,673,678,683],{},[243,674,675],{},[187,676,677],{},"products.similar(slug, query?)",[243,679,680],{},[187,681,682],{},"GET \u002Fproducts\u002F:slug\u002Fsimilar",[243,684,685],{},[187,686,687],{},"PublicProductListItem[]",[228,689,690,695,700],{},[243,691,692],{},[187,693,694],{},"products.priceHistory(slug, query?)",[243,696,697],{},[187,698,699],{},"GET \u002Fproducts\u002F:slug\u002Fprice-history",[243,701,702],{},[187,703,704],{},"PublicPriceHistory",[228,706,707,712,717],{},[243,708,709],{},[187,710,711],{},"merchants.list(query?)",[243,713,714],{},[187,715,716],{},"GET \u002Fmerchants",[243,718,719],{},[187,720,721],{},"Page\u003CPublicMerchantListItem>",[228,723,724,729,734],{},[243,725,726],{},[187,727,728],{},"merchants.get(slug, query?)",[243,730,731],{},[187,732,733],{},"GET \u002Fmerchants\u002F:slug",[243,735,736],{},[187,737,738],{},"PublicMerchant",[228,740,741,746,751],{},[243,742,743],{},[187,744,745],{},"sitemap(query?)",[243,747,748],{},[187,749,750],{},"GET \u002Fsitemap",[243,752,753],{},[187,754,755],{},"PublicSitemap",[228,757,758,763,768],{},[243,759,760],{},[187,761,762],{},"search(query)",[243,764,765],{},[187,766,767],{},"GET \u002Fsearch",[243,769,770],{},[187,771,772],{},"PublicSearchResult",[228,774,775,780,785],{},[243,776,777],{},[187,778,779],{},"outbound.resolve(offerId, s)",[243,781,782],{},[187,783,784],{},"GET \u002Fgo\u002F:offerId",[243,786,787],{},[187,788,789],{},"PublicOutboundResolution",[228,791,792,797,802],{},[243,793,794],{},[187,795,796],{},"outbound.reportClicks(clicks)",[243,798,799],{},[187,800,801],{},"POST \u002Fclicks",[243,803,804],{},[187,805,806],{},"PublicClickReportResult",[184,808,809,812,813,816,817,819],{},[187,810,811],{},"search"," accepts either a string or ",[187,814,815],{},"{ q, types, limit }",". Query arguments are the partial output types of the schemas, so defaults apply when you leave a field out. The parameters are listed on the ",[192,818,194],{"href":166}," page.",[311,821,823],{"className":313,"code":822,"language":315,"meta":316,"style":316},"const listings = createListingsClient({ baseURL, token, locale: 'nb-NO' })\n\nconst site = await listings.website()\nconst page = await listings.products.list({ brand: 'xqs', sort: 'minPrice', pageSize: 12 })\nconst product = await listings.products.get('ettan-loos')\nconst history = await listings.products.priceHistory('ettan-loos', { days: 30 })\nconst found = await listings.search({ q: 'tropical', types: ['product', 'brand'] })\n",[187,824,825,866,870,893,961,994,1040],{"__ignoreMap":316},[320,826,827,830,832,834,836,838,841,844,846,849,851,854,856,858,860,862,864],{"class":322,"line":323},[320,828,829],{"class":373},"const",[320,831,377],{"class":341},[320,833,380],{"class":337},[320,835,342],{"class":389},[320,837,392],{"class":341},[320,839,840],{"class":337},"{",[320,842,843],{"class":341}," baseURL",[320,845,419],{"class":337},[320,847,848],{"class":341}," token",[320,850,419],{"class":337},[320,852,853],{"class":401}," locale",[320,855,405],{"class":337},[320,857,351],{"class":337},[320,859,457],{"class":354},[320,861,460],{"class":337},[320,863,345],{"class":337},[320,865,472],{"class":341},[320,867,868],{"class":322,"line":330},[320,869,364],{"emptyLinePlaceholder":363},[320,871,872,874,877,879,882,885,887,890],{"class":322,"line":360},[320,873,829],{"class":373},[320,875,876],{"class":341}," site ",[320,878,380],{"class":337},[320,880,881],{"class":333}," await",[320,883,884],{"class":341}," listings",[320,886,215],{"class":337},[320,888,889],{"class":389},"website",[320,891,892],{"class":341},"()\n",[320,894,895,897,900,902,904,906,908,911,913,916,918,920,923,925,927,930,932,934,937,939,941,944,946,948,951,953,957,959],{"class":322,"line":367},[320,896,829],{"class":373},[320,898,899],{"class":341}," page ",[320,901,380],{"class":337},[320,903,881],{"class":333},[320,905,884],{"class":341},[320,907,215],{"class":337},[320,909,910],{"class":341},"products",[320,912,215],{"class":337},[320,914,915],{"class":389},"list",[320,917,392],{"class":341},[320,919,840],{"class":337},[320,921,922],{"class":401}," brand",[320,924,405],{"class":337},[320,926,351],{"class":337},[320,928,929],{"class":354},"xqs",[320,931,460],{"class":337},[320,933,419],{"class":337},[320,935,936],{"class":401}," sort",[320,938,405],{"class":337},[320,940,351],{"class":337},[320,942,943],{"class":354},"minPrice",[320,945,460],{"class":337},[320,947,419],{"class":337},[320,949,950],{"class":401}," pageSize",[320,952,405],{"class":337},[320,954,956],{"class":955},"sbssI"," 12",[320,958,345],{"class":337},[320,960,472],{"class":341},[320,962,963,965,968,970,972,974,976,978,980,983,985,987,990,992],{"class":322,"line":398},[320,964,829],{"class":373},[320,966,967],{"class":341}," product ",[320,969,380],{"class":337},[320,971,881],{"class":333},[320,973,884],{"class":341},[320,975,215],{"class":337},[320,977,910],{"class":341},[320,979,215],{"class":337},[320,981,982],{"class":389},"get",[320,984,392],{"class":341},[320,986,460],{"class":337},[320,988,989],{"class":354},"ettan-loos",[320,991,460],{"class":337},[320,993,472],{"class":341},[320,995,996,998,1001,1003,1005,1007,1009,1011,1013,1016,1018,1020,1022,1024,1026,1028,1031,1033,1036,1038],{"class":322,"line":425},[320,997,829],{"class":373},[320,999,1000],{"class":341}," history ",[320,1002,380],{"class":337},[320,1004,881],{"class":333},[320,1006,884],{"class":341},[320,1008,215],{"class":337},[320,1010,910],{"class":341},[320,1012,215],{"class":337},[320,1014,1015],{"class":389},"priceHistory",[320,1017,392],{"class":341},[320,1019,460],{"class":337},[320,1021,989],{"class":354},[320,1023,460],{"class":337},[320,1025,419],{"class":337},[320,1027,338],{"class":337},[320,1029,1030],{"class":401}," days",[320,1032,405],{"class":337},[320,1034,1035],{"class":955}," 30",[320,1037,345],{"class":337},[320,1039,472],{"class":341},[320,1041,1042,1044,1047,1049,1051,1053,1055,1057,1059,1061,1064,1066,1068,1071,1073,1075,1078,1080,1083,1085,1088,1090,1092,1094,1097,1099,1102,1104],{"class":322,"line":447},[320,1043,829],{"class":373},[320,1045,1046],{"class":341}," found ",[320,1048,380],{"class":337},[320,1050,881],{"class":333},[320,1052,884],{"class":341},[320,1054,215],{"class":337},[320,1056,811],{"class":389},[320,1058,392],{"class":341},[320,1060,840],{"class":337},[320,1062,1063],{"class":401}," q",[320,1065,405],{"class":337},[320,1067,351],{"class":337},[320,1069,1070],{"class":354},"tropical",[320,1072,460],{"class":337},[320,1074,419],{"class":337},[320,1076,1077],{"class":401}," types",[320,1079,405],{"class":337},[320,1081,1082],{"class":341}," [",[320,1084,460],{"class":337},[320,1086,1087],{"class":354},"product",[320,1089,460],{"class":337},[320,1091,419],{"class":337},[320,1093,351],{"class":337},[320,1095,1096],{"class":354},"brand",[320,1098,460],{"class":337},[320,1100,1101],{"class":341},"] ",[320,1103,469],{"class":337},[320,1105,472],{"class":341},[184,1107,1108,299,1111,1114,1115,215],{},[187,1109,1110],{},"outbound.resolve",[187,1112,1113],{},"outbound.reportClicks"," are meant for self-hosted redirect clients, not for rendering pages. See ",[192,1116,174],{"href":175},[217,1118,1120],{"id":1119},"handle-errors","Handle errors",[184,1122,1123,1124,1126],{},"Every method rejects with a ",[187,1125,255],{},". It never contains the token.",[222,1128,1129,1138],{},[225,1130,1131],{},[228,1132,1133,1136],{},[231,1134,1135],{},"Property",[231,1137,489],{},[238,1139,1140,1179,1189,1202],{},[228,1141,1142,1146],{},[243,1143,1144],{},[187,1145,187],{},[243,1147,1148,252,1151,252,1154,252,1157,252,1160,1163,1164,1167,1168,1170,1171,1173,1174,1176,1177,215],{},[187,1149,1150],{},"unauthorized",[187,1152,1153],{},"not_found",[187,1155,1156],{},"validation",[187,1158,1159],{},"rate_limited",[187,1161,1162],{},"network"," or ",[187,1165,1166],{},"unknown",". Mapped from the status: 401 and 403 to ",[187,1169,1150],{},", 404 to ",[187,1172,1153],{},", 400 and 422 to ",[187,1175,1156],{},", 429 to ",[187,1178,1159],{},[228,1180,1181,1186],{},[243,1182,1183],{},[187,1184,1185],{},"status",[243,1187,1188],{},"The HTTP status when the server answered.",[228,1190,1191,1196],{},[243,1192,1193],{},[187,1194,1195],{},"data",[243,1197,1198,1199,1201],{},"The ",[187,1200,1195],{}," of the error response.",[228,1203,1204,1209],{},[243,1205,1206],{},[187,1207,1208],{},"replacedBySlug",[243,1210,1211],{},"Set on a 404 for a product, brand or merchant that was merged into another one.",[311,1213,1215],{"className":313,"code":1214,"language":315,"meta":316,"style":316},"import { isListingsError } from '@product-comparison\u002Flistings-client'\n\nexport default defineEventHandler(async (event) => {\n  try {\n    return await listings().products.get(getRouterParam(event, 'slug')!)\n  } catch (error) {\n    \u002F\u002F Merged products: redirect permanently to the surviving one.\n    if (isListingsError(error) && error.replacedBySlug) {\n      return sendRedirect(event, `\u002Fproducts\u002F${error.replacedBySlug}`, 301)\n    }\n    throw error\n  }\n})\n",[187,1216,1217,1236,1240,1270,1277,1321,1339,1344,1373,1413,1419,1428,1434],{"__ignoreMap":316},[320,1218,1219,1221,1223,1226,1228,1230,1232,1234],{"class":322,"line":323},[320,1220,334],{"class":333},[320,1222,338],{"class":337},[320,1224,1225],{"class":341}," isListingsError",[320,1227,345],{"class":337},[320,1229,348],{"class":333},[320,1231,351],{"class":337},[320,1233,189],{"class":354},[320,1235,357],{"class":337},[320,1237,1238],{"class":322,"line":330},[320,1239,364],{"emptyLinePlaceholder":363},[320,1241,1242,1244,1247,1250,1252,1255,1258,1262,1265,1267],{"class":322,"line":360},[320,1243,370],{"class":333},[320,1245,1246],{"class":333}," default",[320,1248,1249],{"class":389}," defineEventHandler",[320,1251,392],{"class":341},[320,1253,1254],{"class":373},"async",[320,1256,1257],{"class":337}," (",[320,1259,1261],{"class":1260},"sHdIc","event",[320,1263,1264],{"class":337},")",[320,1266,386],{"class":373},[320,1268,1269],{"class":337}," {\n",[320,1271,1272,1275],{"class":322,"line":367},[320,1273,1274],{"class":333},"  try",[320,1276,1269],{"class":337},[320,1278,1279,1282,1284,1286,1288,1290,1292,1294,1296,1298,1301,1303,1305,1307,1309,1312,1314,1316,1319],{"class":322,"line":398},[320,1280,1281],{"class":333},"    return",[320,1283,881],{"class":333},[320,1285,884],{"class":389},[320,1287,411],{"class":401},[320,1289,215],{"class":337},[320,1291,910],{"class":341},[320,1293,215],{"class":337},[320,1295,982],{"class":389},[320,1297,392],{"class":401},[320,1299,1300],{"class":389},"getRouterParam",[320,1302,392],{"class":401},[320,1304,1261],{"class":341},[320,1306,419],{"class":337},[320,1308,351],{"class":337},[320,1310,1311],{"class":354},"slug",[320,1313,460],{"class":337},[320,1315,1264],{"class":401},[320,1317,1318],{"class":337},"!",[320,1320,472],{"class":401},[320,1322,1323,1326,1329,1331,1334,1337],{"class":322,"line":425},[320,1324,1325],{"class":337},"  }",[320,1327,1328],{"class":333}," catch",[320,1330,1257],{"class":401},[320,1332,1333],{"class":341},"error",[320,1335,1336],{"class":401},") ",[320,1338,395],{"class":337},[320,1340,1341],{"class":322,"line":447},[320,1342,1343],{"class":326},"    \u002F\u002F Merged products: redirect permanently to the surviving one.\n",[320,1345,1346,1349,1351,1353,1355,1357,1359,1362,1365,1367,1369,1371],{"class":322,"line":466},[320,1347,1348],{"class":333},"    if",[320,1350,1257],{"class":401},[320,1352,258],{"class":389},[320,1354,392],{"class":401},[320,1356,1333],{"class":341},[320,1358,1336],{"class":401},[320,1360,1361],{"class":337},"&&",[320,1363,1364],{"class":341}," error",[320,1366,215],{"class":337},[320,1368,1208],{"class":341},[320,1370,1336],{"class":401},[320,1372,395],{"class":337},[320,1374,1376,1379,1382,1384,1386,1388,1391,1394,1397,1399,1401,1403,1406,1408,1411],{"class":322,"line":1375},9,[320,1377,1378],{"class":333},"      return",[320,1380,1381],{"class":389}," sendRedirect",[320,1383,392],{"class":401},[320,1385,1261],{"class":341},[320,1387,419],{"class":337},[320,1389,1390],{"class":337}," `",[320,1392,1393],{"class":354},"\u002Fproducts\u002F",[320,1395,1396],{"class":337},"${",[320,1398,1333],{"class":341},[320,1400,215],{"class":337},[320,1402,1208],{"class":341},[320,1404,1405],{"class":337},"}`",[320,1407,419],{"class":337},[320,1409,1410],{"class":955}," 301",[320,1412,472],{"class":401},[320,1414,1416],{"class":322,"line":1415},10,[320,1417,1418],{"class":337},"    }\n",[320,1420,1422,1425],{"class":322,"line":1421},11,[320,1423,1424],{"class":333},"    throw",[320,1426,1427],{"class":341}," error\n",[320,1429,1431],{"class":322,"line":1430},12,[320,1432,1433],{"class":337},"  }\n",[320,1435,1437,1439],{"class":322,"line":1436},13,[320,1438,469],{"class":337},[320,1440,472],{"class":341},[217,1442,1444],{"id":1443},"use-the-schemas","Use the schemas",[184,1446,1198,1447,1450],{},[187,1448,1449],{},"\u002Fschema"," entry exports the zod schemas the platform validates requests with. Use them to validate your own incoming query strings with the same names, defaults and limits:",[311,1452,1454],{"className":313,"code":1453,"language":315,"meta":316,"style":316},"import { productListQuerySchema } from '@product-comparison\u002Flistings-client\u002Fschema'\n\nconst query = productListQuerySchema.parse(getQuery(event))\n",[187,1455,1456,1475,1479],{"__ignoreMap":316},[320,1457,1458,1460,1462,1465,1467,1469,1471,1473],{"class":322,"line":323},[320,1459,334],{"class":333},[320,1461,338],{"class":337},[320,1463,1464],{"class":341}," productListQuerySchema",[320,1466,345],{"class":337},[320,1468,348],{"class":333},[320,1470,351],{"class":337},[320,1472,289],{"class":354},[320,1474,357],{"class":337},[320,1476,1477],{"class":322,"line":330},[320,1478,364],{"emptyLinePlaceholder":363},[320,1480,1481,1483,1486,1488,1490,1492,1495,1497,1500],{"class":322,"line":360},[320,1482,829],{"class":373},[320,1484,1485],{"class":341}," query ",[320,1487,380],{"class":337},[320,1489,1464],{"class":341},[320,1491,215],{"class":337},[320,1493,1494],{"class":389},"parse",[320,1496,392],{"class":341},[320,1498,1499],{"class":389},"getQuery",[320,1501,1502],{"class":341},"(event))\n",[184,1504,1505,1506,1509,1510,1513,1514,215],{},"It also exports ",[187,1507,1508],{},"MAX_CLICK_BATCH"," (100), ",[187,1511,1512],{},"MAX_CLICKS_PER_ENTRY"," (1000) and ",[187,1515,302],{},[217,1517,1519],{"id":1518},"related-helpers","Related helpers",[1521,1522,1523,1538],"ul",{},[1524,1525,1526,1529,1530,1533,1534,1537],"li",{},[187,1527,1528],{},"@product-comparison\u002Fcatalog-kit"," provides ",[187,1531,1532],{},"applyTitleTemplate",", JSON-LD builders and ",[187,1535,1536],{},"buildSitemapXml"," for rendering what the API returns.",[1524,1539,1540,1543],{},[187,1541,1542],{},"@product-comparison\u002Fredirect"," is a self-hostable redirect client built on this package.",[1545,1546,1547],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":316,"searchDepth":330,"depth":330,"links":1549},[1550,1551,1554,1555,1556,1557],{"id":219,"depth":330,"text":220},{"id":305,"depth":330,"text":306,"children":1552},[1553],{"id":476,"depth":360,"text":477},{"id":568,"depth":330,"text":569},{"id":1119,"depth":330,"text":1120},{"id":1443,"depth":330,"text":1444},{"id":1518,"depth":330,"text":1519},"Use the typed @product-comparison\u002Flistings-client package to call the public API from a website's server code.","md",null,{},{"icon":52},{"title":170,"description":1564},"Install and use createListingsClient, handle ListingsError, and validate queries with the zod schemas of the listings client package.","1FC3ye4tRJ9O52h52cQNYlPJ0BJGUI1zZFUQfIHF5fI",[1567,1569],{"title":165,"path":166,"stem":167,"description":1568,"icon":168,"children":-1},"Reference of the read-only HTTP API that comparison websites use to show brands, products, merchants and prices.",{"title":174,"path":175,"stem":176,"description":1570,"icon":177,"children":-1},"How outbound links count clicks, how to serve them from your own domain, and where clicks appear in the platform.",1792440615753]