/**
* Fetch IKEA product name and canonical ID via Search API
*/
function getIkeaProductInfo($country, $productId) {
$country = strtolower($country);
$lang = ($country == 'ca') ? 'en' : 'en'; // Simple map for now
$url = "https://sik.search.blue.cdtapps.com/{$country}/{$lang}/search-result-page?q={$productId}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Accept: application/json",
"Referer: https://www.ikea.com/{$country}/{$lang}/"
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode != 200 || !$response) {
return ['name' => "Article $productId", 'canonical_id' => $productId];
}
$data = json_decode($response, true);
$items = $data['searchResultPage']['products']['main']['items'] ?? [];
foreach ($items as $item) {
$p = $item['product'] ?? [];
$itemNo = $p['itemNo'] ?? '';
$name = $p['name'] ?? '';
$type = $p['typeName'] ?? '';
if ($itemNo == $productId || stripos($name, $productId) !== false) {
return [
'name' => trim("$name $type"),
'canonical_id' => $itemNo
];
}
}
return ['name' => "Article $productId", 'canonical_id' => $productId];
}
/**
* Fetch IKEA stock availability
*/
function getIkeaAvailability($country, $productId, $canonicalId, $storeId = null) {
if (!$canonicalId) return ['stock' => 0, 'status' => "Invalid ID", 'restock' => null];
$baseUrl = "https://api.ingka.ikea.com/cia/availabilities";
$clientId = "da465052-7912-43b2-82fa-9dc39cdccef8";
if ($storeId) {
$url = "{$baseUrl}/sto/{$storeId}?itemNos={$canonicalId}&expand=Restocks";
} else {
$url = "{$baseUrl}/ru/" . strtolower($country) . "?itemNos={$canonicalId}&expand=Restocks";
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-Client-ID: $clientId",
"Accept: application/json;version=1",
"Referer: https://www.ikea.com/",
"Origin: https://www.ikea.com"
]);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36");
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 403) {
return [
'stock' => 0,
'status' => "Blocked (403)",
'restock' => null
];
}
if ($httpCode != 200 || !$response) {
return [
'stock' => 0,
'status' => "API Error ($httpCode)",
'restock' => null
];
}
$data = json_decode($response, true);
$availabilities = $data['availabilities'] ?? [];
if (empty($availabilities)) {
return [
'stock' => 0,
'status' => "Not Found",
'restock' => null
];
}
// Usually there's only one item in the list for a specific sto/ru call with one itemNo
$item = $availabilities[0];
$avail = $item['buyingOption']['cashCarry']['availability'] ?? null;
if (!$avail && $item['classUnitKey']['classUnitType'] == 'RU') {
$avail = $item['buyingOption']['homeDelivery']['availability'] ?? null;
}
if (!$avail) {
return [
'stock' => 0,
'status' => "No Data",
'restock' => null
];
}
$stock = $avail['quantity'] ?? 0;
$prob = $avail['probability']['thisDay']['messageType'] ?? 'UNKNOWN';
$restock = null;
$restocks = $avail['restocks'] ?? [];
if (!empty($restocks)) {
$restock = $restocks[0]['earliestDate'] ?? $restocks[0]['date'] ?? null;
}
return [
'stock' => $stock,
'status' => strtoupper($prob),
'restock' => $restock
];
}
/**
* List of stores for selection
*/
function getIkeaStores($country) {
// Subset of stores for CA as requested
$stores = [
'ca' => [
['buCode' => '216', 'name' => 'Calgary'],
['buCode' => '004', 'name' => 'Ottawa'],
['buCode' => '149', 'name' => 'Toronto North York'],
['buCode' => '039', 'name' => 'Montréal'],
['buCode' => '003', 'name' => 'Vancouver Richmond'],
['buCode' => '659', 'name' => 'Toronto Downtown'],
['buCode' => '313', 'name' => 'Coquitlam'],
['buCode' => '349', 'name' => 'Edmonton'],
['buCode' => '256', 'name' => 'Etobicoke'],
['buCode' => '529', 'name' => 'Halifax'],
['buCode' => '559', 'name' => 'Québec City'],
['buCode' => '372', 'name' => 'Vaughan'],
['buCode' => '249', 'name' => 'Winnipeg'],
['buCode' => '414', 'name' => 'Boucherville'],
['buCode' => '040', 'name' => 'Burlington'],
]
];
return $stores[strtolower($country)] ?? [];
}
?>