Complete Walmart toolkit: Export product data, track prices, automate tasks, and enhance shopping experience
Size
56.8 KB
Version
3.0.1
Created
Jan 21, 2026
Updated
13 days ago
1// ==UserScript==
2// @name Walmart Power Tools - Data Export & Automation Suite
3// @description Complete Walmart toolkit: Export product data, track prices, automate tasks, and enhance shopping experience
4// @version 3.0.1
5// @match https://*.walmart.com/*
6// @match https://walmart.com/*
7// @icon https://www.gstatic.com/images/branding/searchlogo/ico/favicon.ico
8// @grant GM.getValue
9// @grant GM.setValue
10// @grant GM.deleteValue
11// @grant GM.listValues
12// @grant GM.setClipboard
13// @grant GM.xmlhttpRequest
14// @grant GM.openInTab
15// @grant GM.notification
16// ==/UserScript==
17(function() {
18 'use strict';
19
20 // ============================================
21 // UTILITY FUNCTIONS
22 // ============================================
23
24 function debounce(func, wait) {
25 let timeout;
26 return function executedFunction(...args) {
27 const later = () => {
28 clearTimeout(timeout);
29 func(...args);
30 };
31 clearTimeout(timeout);
32 timeout = setTimeout(later, wait);
33 };
34 }
35
36 function formatPrice(price) {
37 if (typeof price === 'number') return `$${price.toFixed(2)}`;
38 return price;
39 }
40
41 function downloadJSON(data, filename) {
42 const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
43 const url = URL.createObjectURL(blob);
44 const a = document.createElement('a');
45 a.href = url;
46 a.download = filename;
47 a.click();
48 URL.revokeObjectURL(url);
49 }
50
51 function downloadCSV(data, filename) {
52 if (!data || data.length === 0) return;
53
54 const headers = Object.keys(data[0]);
55 const csvContent = [
56 headers.join(','),
57 ...data.map(row => headers.map(header => {
58 const value = row[header] || '';
59 return `"${String(value).replace(/"/g, '""')}"`;
60 }).join(','))
61 ].join('\n');
62
63 const blob = new Blob([csvContent], { type: 'text/csv' });
64 const url = URL.createObjectURL(blob);
65 const a = document.createElement('a');
66 a.href = url;
67 a.download = filename;
68 a.click();
69 URL.revokeObjectURL(url);
70 }
71
72 function sleep(ms) {
73 return new Promise(resolve => setTimeout(resolve, ms));
74 }
75
76 // ============================================
77 // DEEP SCRAPING FUNCTIONS
78 // ============================================
79
80 async function deepScrapeWithPagination(maxPages = 10) {
81 showNotification('Starting deep scrape...', 'info');
82 const allProducts = [];
83 let currentPage = 1;
84
85 while (currentPage <= maxPages) {
86 console.log(`Scraping page ${currentPage}...`);
87
88 // Extract products from current page
89 const products = extractMultipleProducts();
90 allProducts.push(...products);
91
92 showNotification(`Scraped page ${currentPage}: ${products.length} products`, 'info');
93
94 // Look for next page button
95 const nextButton = document.querySelector('a[aria-label="Next page"]') ||
96 document.querySelector('[data-automation-id="pagination-next"]') ||
97 document.querySelector('.paginator-btn.paginator-next:not(.disabled)');
98
99 if (!nextButton || nextButton.disabled || nextButton.classList.contains('disabled')) {
100 console.log('No more pages found');
101 break;
102 }
103
104 // Click next page
105 nextButton.click();
106 await sleep(3000); // Wait for page to load
107
108 currentPage++;
109 }
110
111 showNotification(`Deep scrape complete! Found ${allProducts.length} products`, 'success');
112 return allProducts;
113 }
114
115 async function scrapeWithInfiniteScroll(scrollAttempts = 20) {
116 showNotification('Starting infinite scroll scrape...', 'info');
117 const allProducts = new Set();
118 let lastProductCount = 0;
119 let noChangeCount = 0;
120
121 for (let i = 0; i < scrollAttempts; i++) {
122 // Scroll to bottom
123 window.scrollTo(0, document.body.scrollHeight);
124 await sleep(2000);
125
126 // Extract current products
127 const products = extractMultipleProducts();
128 const currentCount = products.length;
129
130 // Add to set (automatically handles duplicates)
131 products.forEach(p => allProducts.add(JSON.stringify(p)));
132
133 console.log(`Scroll ${i + 1}: Found ${currentCount} products (total unique: ${allProducts.size})`);
134
135 // Check if we're getting new products
136 if (currentCount === lastProductCount) {
137 noChangeCount++;
138 if (noChangeCount >= 3) {
139 console.log('No new products found after 3 attempts, stopping');
140 break;
141 }
142 } else {
143 noChangeCount = 0;
144 }
145
146 lastProductCount = currentCount;
147 showNotification(`Scroll ${i + 1}: ${allProducts.size} unique products`, 'info');
148 }
149
150 const uniqueProducts = Array.from(allProducts).map(p => JSON.parse(p));
151 showNotification(`Infinite scroll complete! Found ${uniqueProducts.length} unique products`, 'success');
152 return uniqueProducts;
153 }
154
155 async function deepProductAnalysis(productUrl) {
156 showNotification('Fetching detailed product data...', 'info');
157
158 return new Promise((resolve, reject) => {
159 GM.xmlhttpRequest({
160 method: 'GET',
161 url: productUrl,
162 onload: function(response) {
163 const parser = new DOMParser();
164 const doc = parser.parseFromString(response.responseText, 'text/html');
165
166 const deepData = {
167 basicInfo: extractSingleProductFromDoc(doc),
168 specifications: extractSpecifications(doc),
169 reviews: extractReviews(doc),
170 shipping: extractShippingInfo(doc),
171 seller: extractSellerInfo(doc),
172 relatedProducts: extractRelatedProducts(doc)
173 };
174
175 resolve(deepData);
176 },
177 onerror: function(error) {
178 console.error('Error fetching product:', error);
179 reject(error);
180 }
181 });
182 });
183 }
184
185 function extractSingleProductFromDoc(doc) {
186 const product = {};
187
188 const nameEl = doc.querySelector('h1[itemprop="name"]') || doc.querySelector('[data-testid="product-title"]');
189 product.name = nameEl ? nameEl.textContent.trim() : 'Unknown';
190
191 const priceEl = doc.querySelector('[itemprop="price"]') || doc.querySelector('[data-testid="price-wrap"] span');
192 product.price = priceEl ? priceEl.textContent.trim() : 'N/A';
193
194 const ratingEl = doc.querySelector('[itemprop="ratingValue"]');
195 product.rating = ratingEl ? ratingEl.textContent.trim() : 'N/A';
196
197 const reviewEl = doc.querySelector('[itemprop="reviewCount"]');
198 product.reviews = reviewEl ? reviewEl.textContent.trim() : 'N/A';
199
200 return product;
201 }
202
203 function extractSpecifications(doc) {
204 const specs = {};
205 const specElements = doc.querySelectorAll('[data-testid="product-specification"] tr, .product-specification-table tr');
206
207 specElements.forEach(row => {
208 const label = row.querySelector('td:first-child, th');
209 const value = row.querySelector('td:last-child');
210 if (label && value) {
211 specs[label.textContent.trim()] = value.textContent.trim();
212 }
213 });
214
215 return specs;
216 }
217
218 function extractReviews(doc) {
219 const reviews = [];
220 const reviewElements = doc.querySelectorAll('[data-testid="review-item"], .review-item');
221
222 reviewElements.forEach(review => {
223 const rating = review.querySelector('[class*="rating"]')?.textContent.trim();
224 const text = review.querySelector('[class*="review-text"]')?.textContent.trim();
225 const author = review.querySelector('[class*="review-author"]')?.textContent.trim();
226
227 if (rating || text) {
228 reviews.push({ rating, text, author });
229 }
230 });
231
232 return reviews;
233 }
234
235 function extractShippingInfo(doc) {
236 const shippingEl = doc.querySelector('[data-testid="fulfillment-shipping"]') ||
237 doc.querySelector('.shipping-info');
238 return shippingEl ? shippingEl.textContent.trim() : 'N/A';
239 }
240
241 function extractSellerInfo(doc) {
242 const sellerEl = doc.querySelector('[data-testid="seller-name"]') ||
243 doc.querySelector('.seller-info');
244 return sellerEl ? sellerEl.textContent.trim() : 'Walmart';
245 }
246
247 function extractRelatedProducts(doc) {
248 const related = [];
249 const relatedElements = doc.querySelectorAll('[data-testid="related-product"], .similar-product');
250
251 relatedElements.forEach(el => {
252 const name = el.querySelector('[data-automation-id="product-title"]')?.textContent.trim();
253 const price = el.querySelector('[data-automation-id="product-price"]')?.textContent.trim();
254 const url = el.querySelector('a')?.href;
255
256 if (name) {
257 related.push({ name, price, url });
258 }
259 });
260
261 return related;
262 }
263
264 // ============================================
265 // AI-POWERED ANALYSIS
266 // ============================================
267
268 async function aiAnalyzeProduct(productData) {
269 showNotification('AI analyzing product...', 'info');
270
271 try {
272 const prompt = `Analyze this Walmart product and provide insights:
273Product: ${productData.name}
274Price: ${productData.price}
275Rating: ${productData.rating}
276Reviews: ${productData.reviews}
277Description: ${productData.description || 'N/A'}
278
279Provide:
2801. Value assessment (is it a good deal?)
2812. Key pros and cons
2823. Best use cases
2834. Comparison to similar products
2845. Purchase recommendation`;
285
286 const analysis = await RM.aiCall(prompt);
287 return analysis;
288 } catch (error) {
289 console.error('AI analysis error:', error);
290 return 'AI analysis unavailable';
291 }
292 }
293
294 async function aiCompareProducts(products) {
295 showNotification('AI comparing products...', 'info');
296
297 try {
298 const productList = products.map((p, i) =>
299 `${i + 1}. ${p.name} - ${p.price} (Rating: ${p.rating})`
300 ).join('\n');
301
302 const prompt = `Compare these Walmart products and recommend the best option:
303${productList}
304
305Provide:
3061. Best overall value
3072. Best for budget
3083. Best quality
3094. Key differences
3105. Final recommendation with reasoning`;
311
312 const comparison = await RM.aiCall(prompt);
313 return comparison;
314 } catch (error) {
315 console.error('AI comparison error:', error);
316 return 'AI comparison unavailable';
317 }
318 }
319
320 async function aiPricePredictor(priceHistory) {
321 try {
322 const historyText = priceHistory.map(h =>
323 `${new Date(h.timestamp).toLocaleDateString()}: $${h.price}`
324 ).join('\n');
325
326 const prompt = `Based on this price history, predict future price trends:
327${historyText}
328
329Provide:
3301. Price trend (increasing/decreasing/stable)
3312. Best time to buy
3323. Expected price range in next 30 days
3334. Deal probability score (0-100)`;
334
335 const prediction = await RM.aiCall(prompt);
336 return prediction;
337 } catch (error) {
338 console.error('AI prediction error:', error);
339 return 'Price prediction unavailable';
340 }
341 }
342
343 // ============================================
344 // DATA EXTRACTION FUNCTIONS
345 // ============================================
346
347 function extractProductData() {
348 console.log('Extracting product data from current page...');
349
350 const productData = {
351 url: window.location.href,
352 timestamp: new Date().toISOString(),
353 products: []
354 };
355
356 const isProductPage = window.location.pathname.includes('/ip/');
357
358 if (isProductPage) {
359 const product = extractSingleProduct();
360 if (product) productData.products.push(product);
361 } else {
362 const products = extractMultipleProducts();
363 productData.products = products;
364 }
365
366 console.log(`Extracted ${productData.products.length} products`);
367 return productData;
368 }
369
370 function extractSingleProduct() {
371 try {
372 const product = {};
373
374 const nameEl = document.querySelector('h1[itemprop="name"]') ||
375 document.querySelector('[data-testid="product-title"]') ||
376 document.querySelector('h1');
377 product.name = nameEl ? nameEl.textContent.trim() : 'Unknown';
378
379 const priceEl = document.querySelector('[itemprop="price"]') ||
380 document.querySelector('[data-testid="price-wrap"] span') ||
381 document.querySelector('.price-characteristic');
382 product.price = priceEl ? priceEl.textContent.trim() : 'N/A';
383
384 const ratingEl = document.querySelector('[itemprop="ratingValue"]') ||
385 document.querySelector('.rating-number');
386 product.rating = ratingEl ? ratingEl.textContent.trim() : 'N/A';
387
388 const reviewEl = document.querySelector('[itemprop="reviewCount"]') ||
389 document.querySelector('.review-count');
390 product.reviews = reviewEl ? reviewEl.textContent.trim() : 'N/A';
391
392 const urlMatch = window.location.pathname.match(/\/ip\/[^\/]+\/(\d+)/);
393 product.id = urlMatch ? urlMatch[1] : 'N/A';
394
395 const imgEl = document.querySelector('[data-testid="hero-image-container"] img') ||
396 document.querySelector('.prod-hero-image img');
397 product.image = imgEl ? imgEl.src : 'N/A';
398
399 const descEl = document.querySelector('[itemprop="description"]') ||
400 document.querySelector('.about-desc');
401 product.description = descEl ? descEl.textContent.trim().substring(0, 200) : 'N/A';
402
403 const availEl = document.querySelector('[data-testid="fulfillment-badge"]') ||
404 document.querySelector('.prod-ProductOffer-oosMsg');
405 product.availability = availEl ? availEl.textContent.trim() : 'In Stock';
406
407 const brandEl = document.querySelector('[itemprop="brand"]') ||
408 document.querySelector('.prod-brandName');
409 product.brand = brandEl ? brandEl.textContent.trim() : 'N/A';
410
411 product.url = window.location.href;
412
413 console.log('Extracted single product:', product);
414 return product;
415 } catch (error) {
416 console.error('Error extracting single product:', error);
417 return null;
418 }
419 }
420
421 function extractMultipleProducts() {
422 const products = [];
423
424 const productSelectors = [
425 '[data-item-id]',
426 '[data-testid="list-view"]',
427 '.search-result-gridview-item',
428 '[data-automation-id="product-tile"]'
429 ];
430
431 let productElements = [];
432 for (const selector of productSelectors) {
433 productElements = document.querySelectorAll(selector);
434 if (productElements.length > 0) break;
435 }
436
437 console.log(`Found ${productElements.length} product elements`);
438
439 productElements.forEach((el, index) => {
440 try {
441 const product = {};
442
443 const nameEl = el.querySelector('[data-automation-id="product-title"]') ||
444 el.querySelector('a[link-identifier*="product"]') ||
445 el.querySelector('.product-title-link');
446 product.name = nameEl ? nameEl.textContent.trim() : `Product ${index + 1}`;
447
448 const priceEl = el.querySelector('[data-automation-id="product-price"]') ||
449 el.querySelector('.price-main') ||
450 el.querySelector('[class*="price"]');
451 product.price = priceEl ? priceEl.textContent.trim() : 'N/A';
452
453 const ratingEl = el.querySelector('.stars-reviews-count') ||
454 el.querySelector('[class*="rating"]');
455 product.rating = ratingEl ? ratingEl.textContent.trim() : 'N/A';
456
457 const linkEl = el.querySelector('a[href*="/ip/"]');
458 product.url = linkEl ? 'https://www.walmart.com' + linkEl.getAttribute('href') : 'N/A';
459
460 const itemId = el.getAttribute('data-item-id');
461 product.id = itemId || 'N/A';
462
463 const imgEl = el.querySelector('img');
464 product.image = imgEl ? imgEl.src : 'N/A';
465
466 products.push(product);
467 } catch (error) {
468 console.error(`Error extracting product ${index}:`, error);
469 }
470 });
471
472 return products;
473 }
474
475 // ============================================
476 // PRICE TRACKING & ALERTS
477 // ============================================
478
479 async function savePriceHistory(productId, price, name) {
480 const key = `price_history_${productId}`;
481 let history = await GM.getValue(key, []);
482
483 if (typeof history === 'string') {
484 history = JSON.parse(history);
485 }
486
487 history.push({
488 price: price,
489 timestamp: new Date().toISOString(),
490 name: name
491 });
492
493 if (history.length > 100) {
494 history = history.slice(-100);
495 }
496
497 await GM.setValue(key, JSON.stringify(history));
498 console.log(`Saved price history for product ${productId}`);
499
500 // Check for price alerts
501 await checkPriceAlert(productId, price, name);
502 }
503
504 async function getPriceHistory(productId) {
505 const key = `price_history_${productId}`;
506 let history = await GM.getValue(key, []);
507
508 if (typeof history === 'string') {
509 history = JSON.parse(history);
510 }
511
512 return history;
513 }
514
515 async function setPriceAlert(productId, targetPrice, productName) {
516 const alerts = await GM.getValue('price_alerts', {});
517 alerts[productId] = {
518 targetPrice: targetPrice,
519 productName: productName,
520 createdAt: new Date().toISOString()
521 };
522 await GM.setValue('price_alerts', alerts);
523 showNotification(`Price alert set for ${productName} at $${targetPrice}`, 'success');
524 }
525
526 async function checkPriceAlert(productId, currentPrice, productName) {
527 const alerts = await GM.getValue('price_alerts', {});
528
529 if (alerts[productId] && currentPrice <= alerts[productId].targetPrice) {
530 GM.notification({
531 title: '🎉 Price Alert!',
532 text: `${productName} is now $${currentPrice}! (Target: $${alerts[productId].targetPrice})`,
533 timeout: 10000
534 });
535
536 showNotification(`Price alert triggered for ${productName}!`, 'success');
537 }
538 }
539
540 async function trackCurrentProduct() {
541 const product = extractSingleProduct();
542 if (!product || product.id === 'N/A') {
543 showNotification('Cannot track this product', 'error');
544 return;
545 }
546
547 const priceMatch = product.price.match(/[\d.]+/);
548 const numericPrice = priceMatch ? parseFloat(priceMatch[0]) : 0;
549
550 await savePriceHistory(product.id, numericPrice, product.name);
551
552 let trackedProducts = await GM.getValue('tracked_products', []);
553 if (typeof trackedProducts === 'string') {
554 trackedProducts = JSON.parse(trackedProducts);
555 }
556
557 const existingIndex = trackedProducts.findIndex(p => p.id === product.id);
558 if (existingIndex >= 0) {
559 trackedProducts[existingIndex] = {
560 id: product.id,
561 name: product.name,
562 url: product.url,
563 currentPrice: numericPrice,
564 lastChecked: new Date().toISOString()
565 };
566 } else {
567 trackedProducts.push({
568 id: product.id,
569 name: product.name,
570 url: product.url,
571 currentPrice: numericPrice,
572 lastChecked: new Date().toISOString()
573 });
574 }
575
576 await GM.setValue('tracked_products', JSON.stringify(trackedProducts));
577 showNotification('Product added to price tracking!', 'success');
578 }
579
580 // ============================================
581 // BULK OPERATIONS
582 // ============================================
583
584 async function bulkExportProducts(products) {
585 showNotification('Performing bulk export...', 'info');
586
587 const detailedProducts = [];
588 for (let i = 0; i < products.length; i++) {
589 if (products[i].url && products[i].url !== 'N/A') {
590 try {
591 const deepData = await deepProductAnalysis(products[i].url);
592 detailedProducts.push(deepData);
593 showNotification(`Exported ${i + 1}/${products.length} products`, 'info');
594 await sleep(1000); // Rate limiting
595 } catch (error) {
596 console.error(`Error exporting product ${i}:`, error);
597 }
598 }
599 }
600
601 downloadJSON(detailedProducts, `walmart-bulk-export-${Date.now()}.json`);
602 showNotification(`Bulk export complete! ${detailedProducts.length} products`, 'success');
603 }
604
605 async function bulkPriceCheck(productIds) {
606 showNotification('Checking prices for all tracked products...', 'info');
607
608 const results = [];
609 for (const id of productIds) {
610 const history = await getPriceHistory(id);
611 if (history.length > 0) {
612 const latest = history[history.length - 1];
613 const oldest = history[0];
614 const priceChange = latest.price - oldest.price;
615 const percentChange = ((priceChange / oldest.price) * 100).toFixed(2);
616
617 results.push({
618 name: latest.name,
619 currentPrice: latest.price,
620 oldestPrice: oldest.price,
621 change: priceChange,
622 percentChange: percentChange
623 });
624 }
625 }
626
627 return results;
628 }
629
630 // ============================================
631 // AUTOMATION FUNCTIONS
632 // ============================================
633
634 async function autoAddToCart() {
635 const addToCartBtn = document.querySelector('[data-automation-id="add-to-cart-button"]') ||
636 document.querySelector('button[data-testid="add-to-cart-button"]') ||
637 document.querySelector('button[aria-label*="Add to cart"]');
638
639 if (addToCartBtn) {
640 addToCartBtn.click();
641 showNotification('Added to cart!', 'success');
642 console.log('Auto-added product to cart');
643 } else {
644 showNotification('Add to cart button not found', 'error');
645 console.error('Could not find add to cart button');
646 }
647 }
648
649 async function autoCheckoutPrep() {
650 showNotification('Preparing checkout...', 'info');
651
652 // Navigate to cart
653 const cartBtn = document.querySelector('[data-automation-id="cart"]') ||
654 document.querySelector('a[href*="/cart"]');
655
656 if (cartBtn) {
657 cartBtn.click();
658 await sleep(2000);
659
660 // Look for checkout button
661 const checkoutBtn = document.querySelector('[data-automation-id="checkout-button"]') ||
662 document.querySelector('button[aria-label*="Proceed to checkout"]');
663
664 if (checkoutBtn) {
665 showNotification('Ready to checkout! Click the checkout button when ready.', 'success');
666 }
667 }
668 }
669
670 function quickSearch(query) {
671 const searchUrl = `https://www.walmart.com/search?q=${encodeURIComponent(query)}`;
672 window.location.href = searchUrl;
673 }
674
675 async function autoFillSearchFilters(filters) {
676 // Auto-apply filters like price range, rating, etc.
677 if (filters.minPrice) {
678 const minPriceInput = document.querySelector('input[name="min-price"]');
679 if (minPriceInput) {
680 minPriceInput.value = filters.minPrice;
681 minPriceInput.dispatchEvent(new Event('input', { bubbles: true }));
682 }
683 }
684
685 if (filters.minRating) {
686 const ratingFilter = document.querySelector(`[data-value="${filters.minRating}"]`);
687 if (ratingFilter) ratingFilter.click();
688 }
689 }
690
691 // ============================================
692 // UI FUNCTIONS
693 // ============================================
694
695 function createControlPanel() {
696 const panel = document.createElement('div');
697 panel.id = 'walmart-power-tools-panel';
698 panel.innerHTML = `
699 <div class="wpt-header">
700 <h3>🛒 Walmart Power Tools Pro</h3>
701 <button class="wpt-close" id="wpt-close-btn">×</button>
702 </div>
703 <div class="wpt-content">
704 <div class="wpt-section">
705 <h4>📊 Data Export</h4>
706 <button class="wpt-btn" id="wpt-export-json">Export as JSON</button>
707 <button class="wpt-btn" id="wpt-export-csv">Export as CSV</button>
708 <button class="wpt-btn" id="wpt-copy-data">Copy to Clipboard</button>
709 <button class="wpt-btn" id="wpt-bulk-export">Bulk Deep Export</button>
710 </div>
711
712 <div class="wpt-section">
713 <h4>🔍 Deep Scraping</h4>
714 <button class="wpt-btn" id="wpt-deep-scrape">Deep Scrape (Pagination)</button>
715 <button class="wpt-btn" id="wpt-infinite-scroll">Infinite Scroll Scrape</button>
716 <button class="wpt-btn" id="wpt-deep-analysis">Deep Product Analysis</button>
717 </div>
718
719 <div class="wpt-section">
720 <h4>🤖 AI Features</h4>
721 <button class="wpt-btn" id="wpt-ai-analyze">AI Product Analysis</button>
722 <button class="wpt-btn" id="wpt-ai-compare">AI Compare Products</button>
723 <button class="wpt-btn" id="wpt-ai-price-predict">AI Price Prediction</button>
724 </div>
725
726 <div class="wpt-section">
727 <h4>💰 Price Tracking</h4>
728 <button class="wpt-btn" id="wpt-track-price">Track This Product</button>
729 <button class="wpt-btn" id="wpt-set-alert">Set Price Alert</button>
730 <button class="wpt-btn" id="wpt-view-tracked">View Tracked Products</button>
731 <button class="wpt-btn" id="wpt-price-history">Price History</button>
732 <button class="wpt-btn" id="wpt-bulk-price-check">Bulk Price Check</button>
733 </div>
734
735 <div class="wpt-section">
736 <h4>⚡ Automation</h4>
737 <button class="wpt-btn" id="wpt-auto-cart">Add to Cart</button>
738 <button class="wpt-btn" id="wpt-auto-checkout">Prepare Checkout</button>
739 <button class="wpt-btn" id="wpt-quick-search">Quick Search</button>
740 <button class="wpt-btn" id="wpt-extract-all">Extract All Data</button>
741 </div>
742
743 <div class="wpt-section">
744 <h4>⚙️ Settings</h4>
745 <button class="wpt-btn" id="wpt-clear-data">Clear All Data</button>
746 <button class="wpt-btn" id="wpt-export-settings">Export Settings</button>
747 </div>
748 </div>
749 `;
750
751 document.body.appendChild(panel);
752 attachPanelListeners();
753 }
754
755 function createFloatingButton() {
756 const btn = document.createElement('button');
757 btn.id = 'walmart-power-tools-fab';
758 btn.innerHTML = '🛒';
759 btn.title = 'Walmart Power Tools Pro';
760
761 btn.addEventListener('click', () => {
762 const panel = document.getElementById('walmart-power-tools-panel');
763 if (panel) {
764 panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
765 } else {
766 createControlPanel();
767 }
768 });
769
770 document.body.appendChild(btn);
771 }
772
773 function attachPanelListeners() {
774 document.getElementById('wpt-close-btn')?.addEventListener('click', () => {
775 document.getElementById('walmart-power-tools-panel').style.display = 'none';
776 });
777
778 // Export buttons
779 document.getElementById('wpt-export-json')?.addEventListener('click', async () => {
780 const data = extractProductData();
781 downloadJSON(data, `walmart-products-${Date.now()}.json`);
782 showNotification('Exported as JSON!', 'success');
783 });
784
785 document.getElementById('wpt-export-csv')?.addEventListener('click', async () => {
786 const data = extractProductData();
787 downloadCSV(data.products, `walmart-products-${Date.now()}.csv`);
788 showNotification('Exported as CSV!', 'success');
789 });
790
791 document.getElementById('wpt-copy-data')?.addEventListener('click', async () => {
792 const data = extractProductData();
793 await GM.setClipboard(JSON.stringify(data, null, 2));
794 showNotification('Copied to clipboard!', 'success');
795 });
796
797 document.getElementById('wpt-bulk-export')?.addEventListener('click', async () => {
798 const data = extractProductData();
799 await bulkExportProducts(data.products);
800 });
801
802 // Deep scraping buttons
803 document.getElementById('wpt-deep-scrape')?.addEventListener('click', async () => {
804 const maxPages = parseInt(prompt('How many pages to scrape?', '5'));
805 if (maxPages) {
806 const products = await deepScrapeWithPagination(maxPages);
807 downloadJSON({ products, timestamp: new Date().toISOString() }, `walmart-deep-scrape-${Date.now()}.json`);
808 }
809 });
810
811 document.getElementById('wpt-infinite-scroll')?.addEventListener('click', async () => {
812 const scrolls = parseInt(prompt('How many scroll attempts?', '20'));
813 if (scrolls) {
814 const products = await scrapeWithInfiniteScroll(scrolls);
815 downloadJSON({ products, timestamp: new Date().toISOString() }, `walmart-scroll-scrape-${Date.now()}.json`);
816 }
817 });
818
819 document.getElementById('wpt-deep-analysis')?.addEventListener('click', async () => {
820 const product = extractSingleProduct();
821 if (product && product.url) {
822 const deepData = await deepProductAnalysis(product.url);
823 showDeepAnalysisModal(deepData);
824 } else {
825 showNotification('No product found on this page', 'error');
826 }
827 });
828
829 // AI buttons
830 document.getElementById('wpt-ai-analyze')?.addEventListener('click', async () => {
831 const product = extractSingleProduct();
832 if (product) {
833 const analysis = await aiAnalyzeProduct(product);
834 showAIResultModal('AI Product Analysis', analysis);
835 } else {
836 showNotification('No product found on this page', 'error');
837 }
838 });
839
840 document.getElementById('wpt-ai-compare')?.addEventListener('click', async () => {
841 const data = extractProductData();
842 if (data.products.length >= 2) {
843 const comparison = await aiCompareProducts(data.products.slice(0, 5));
844 showAIResultModal('AI Product Comparison', comparison);
845 } else {
846 showNotification('Need at least 2 products to compare', 'error');
847 }
848 });
849
850 document.getElementById('wpt-ai-price-predict')?.addEventListener('click', async () => {
851 const product = extractSingleProduct();
852 if (product && product.id !== 'N/A') {
853 const history = await getPriceHistory(product.id);
854 if (history.length > 0) {
855 const prediction = await aiPricePredictor(history);
856 showAIResultModal('AI Price Prediction', prediction);
857 } else {
858 showNotification('No price history available', 'error');
859 }
860 } else {
861 showNotification('No product found on this page', 'error');
862 }
863 });
864
865 // Price tracking buttons
866 document.getElementById('wpt-track-price')?.addEventListener('click', trackCurrentProduct);
867
868 document.getElementById('wpt-set-alert')?.addEventListener('click', async () => {
869 const product = extractSingleProduct();
870 if (product && product.id !== 'N/A') {
871 const targetPrice = parseFloat(prompt('Enter target price for alert:', ''));
872 if (targetPrice) {
873 await setPriceAlert(product.id, targetPrice, product.name);
874 }
875 } else {
876 showNotification('No product found on this page', 'error');
877 }
878 });
879
880 document.getElementById('wpt-view-tracked')?.addEventListener('click', async () => {
881 let trackedProducts = await GM.getValue('tracked_products', []);
882 if (typeof trackedProducts === 'string') {
883 trackedProducts = JSON.parse(trackedProducts);
884 }
885 showTrackedProductsModal(trackedProducts);
886 });
887
888 document.getElementById('wpt-price-history')?.addEventListener('click', async () => {
889 const product = extractSingleProduct();
890 if (product && product.id !== 'N/A') {
891 const history = await getPriceHistory(product.id);
892 showPriceHistoryModal(product.name, history);
893 } else {
894 showNotification('No product found on this page', 'error');
895 }
896 });
897
898 document.getElementById('wpt-bulk-price-check')?.addEventListener('click', async () => {
899 let trackedProducts = await GM.getValue('tracked_products', []);
900 if (typeof trackedProducts === 'string') {
901 trackedProducts = JSON.parse(trackedProducts);
902 }
903 const productIds = trackedProducts.map(p => p.id);
904 const results = await bulkPriceCheck(productIds);
905 showBulkPriceCheckModal(results);
906 });
907
908 // Automation buttons
909 document.getElementById('wpt-auto-cart')?.addEventListener('click', autoAddToCart);
910
911 document.getElementById('wpt-auto-checkout')?.addEventListener('click', autoCheckoutPrep);
912
913 document.getElementById('wpt-quick-search')?.addEventListener('click', () => {
914 const query = prompt('Enter search query:');
915 if (query) quickSearch(query);
916 });
917
918 document.getElementById('wpt-extract-all')?.addEventListener('click', async () => {
919 const data = extractProductData();
920 showNotification(`Extracted ${data.products.length} products!`, 'success');
921 console.log('Extracted data:', data);
922 });
923
924 // Settings buttons
925 document.getElementById('wpt-clear-data')?.addEventListener('click', async () => {
926 if (confirm('Clear all saved data? This cannot be undone.')) {
927 const keys = await GM.listValues();
928 for (const key of keys) {
929 await GM.deleteValue(key);
930 }
931 showNotification('All data cleared!', 'success');
932 }
933 });
934
935 document.getElementById('wpt-export-settings')?.addEventListener('click', async () => {
936 const keys = await GM.listValues();
937 const settings = {};
938 for (const key of keys) {
939 settings[key] = await GM.getValue(key);
940 }
941 downloadJSON(settings, `walmart-settings-${Date.now()}.json`);
942 showNotification('Settings exported!', 'success');
943 });
944 }
945
946 function showNotification(message, type = 'info') {
947 const notification = document.createElement('div');
948 notification.className = `wpt-notification wpt-notification-${type}`;
949 notification.textContent = message;
950
951 document.body.appendChild(notification);
952
953 setTimeout(() => {
954 notification.style.opacity = '0';
955 setTimeout(() => notification.remove(), 300);
956 }, 3000);
957 }
958
959 function showTrackedProductsModal(products) {
960 const modal = document.createElement('div');
961 modal.className = 'wpt-modal';
962 modal.innerHTML = `
963 <div class="wpt-modal-content">
964 <div class="wpt-modal-header">
965 <h3>Tracked Products (${products.length})</h3>
966 <button class="wpt-close">×</button>
967 </div>
968 <div class="wpt-modal-body">
969 ${products.length === 0 ? '<p>No tracked products yet.</p>' :
970 products.map(p => `
971 <div class="wpt-tracked-item">
972 <div class="wpt-tracked-info">
973 <strong>${p.name}</strong>
974 <div>Current Price: ${formatPrice(p.currentPrice)}</div>
975 <div>Last Checked: ${new Date(p.lastChecked).toLocaleString()}</div>
976 </div>
977 <div class="wpt-tracked-actions">
978 <button class="wpt-btn-small" onclick="window.open('${p.url}', '_blank')">View</button>
979 </div>
980 </div>
981 `).join('')
982 }
983 </div>
984 </div>
985 `;
986
987 document.body.appendChild(modal);
988
989 modal.querySelector('.wpt-close').addEventListener('click', () => modal.remove());
990 modal.addEventListener('click', (e) => {
991 if (e.target === modal) modal.remove();
992 });
993 }
994
995 function showPriceHistoryModal(productName, history) {
996 const modal = document.createElement('div');
997 modal.className = 'wpt-modal';
998 modal.innerHTML = `
999 <div class="wpt-modal-content">
1000 <div class="wpt-modal-header">
1001 <h3>Price History: ${productName}</h3>
1002 <button class="wpt-close">×</button>
1003 </div>
1004 <div class="wpt-modal-body">
1005 ${history.length === 0 ? '<p>No price history available.</p>' :
1006 `<div class="wpt-price-history">
1007 ${history.map(h => `
1008 <div class="wpt-history-item">
1009 <span class="wpt-history-price">${formatPrice(h.price)}</span>
1010 <span class="wpt-history-date">${new Date(h.timestamp).toLocaleString()}</span>
1011 </div>
1012 `).join('')}
1013 </div>`
1014 }
1015 </div>
1016 </div>
1017 `;
1018
1019 document.body.appendChild(modal);
1020
1021 modal.querySelector('.wpt-close').addEventListener('click', () => modal.remove());
1022 modal.addEventListener('click', (e) => {
1023 if (e.target === modal) modal.remove();
1024 });
1025 }
1026
1027 function showDeepAnalysisModal(data) {
1028 const modal = document.createElement('div');
1029 modal.className = 'wpt-modal';
1030 modal.innerHTML = `
1031 <div class="wpt-modal-content wpt-modal-large">
1032 <div class="wpt-modal-header">
1033 <h3>Deep Product Analysis</h3>
1034 <button class="wpt-close">×</button>
1035 </div>
1036 <div class="wpt-modal-body">
1037 <h4>Basic Info</h4>
1038 <pre>${JSON.stringify(data.basicInfo, null, 2)}</pre>
1039
1040 <h4>Specifications</h4>
1041 <pre>${JSON.stringify(data.specifications, null, 2)}</pre>
1042
1043 <h4>Reviews (${data.reviews.length})</h4>
1044 <pre>${JSON.stringify(data.reviews.slice(0, 5), null, 2)}</pre>
1045
1046 <h4>Shipping</h4>
1047 <pre>${data.shipping}</pre>
1048
1049 <h4>Seller</h4>
1050 <pre>${data.seller}</pre>
1051
1052 <h4>Related Products (${data.relatedProducts.length})</h4>
1053 <pre>${JSON.stringify(data.relatedProducts.slice(0, 5), null, 2)}</pre>
1054 </div>
1055 </div>
1056 `;
1057
1058 document.body.appendChild(modal);
1059
1060 modal.querySelector('.wpt-close').addEventListener('click', () => modal.remove());
1061 modal.addEventListener('click', (e) => {
1062 if (e.target === modal) modal.remove();
1063 });
1064 }
1065
1066 function showAIResultModal(title, content) {
1067 const modal = document.createElement('div');
1068 modal.className = 'wpt-modal';
1069 modal.innerHTML = `
1070 <div class="wpt-modal-content wpt-modal-large">
1071 <div class="wpt-modal-header">
1072 <h3>${title}</h3>
1073 <button class="wpt-close">×</button>
1074 </div>
1075 <div class="wpt-modal-body">
1076 <div class="wpt-ai-result">${content.replace(/\n/g, '<br>')}</div>
1077 </div>
1078 </div>
1079 `;
1080
1081 document.body.appendChild(modal);
1082
1083 modal.querySelector('.wpt-close').addEventListener('click', () => modal.remove());
1084 modal.addEventListener('click', (e) => {
1085 if (e.target === modal) modal.remove();
1086 });
1087 }
1088
1089 function showBulkPriceCheckModal(results) {
1090 const modal = document.createElement('div');
1091 modal.className = 'wpt-modal';
1092 modal.innerHTML = `
1093 <div class="wpt-modal-content wpt-modal-large">
1094 <div class="wpt-modal-header">
1095 <h3>Bulk Price Check Results</h3>
1096 <button class="wpt-close">×</button>
1097 </div>
1098 <div class="wpt-modal-body">
1099 ${results.length === 0 ? '<p>No price data available.</p>' :
1100 `<table class="wpt-price-table">
1101 <thead>
1102 <tr>
1103 <th>Product</th>
1104 <th>Current Price</th>
1105 <th>Original Price</th>
1106 <th>Change</th>
1107 <th>% Change</th>
1108 </tr>
1109 </thead>
1110 <tbody>
1111 ${results.map(r => `
1112 <tr>
1113 <td>${r.name}</td>
1114 <td>${formatPrice(r.currentPrice)}</td>
1115 <td>${formatPrice(r.oldestPrice)}</td>
1116 <td class="${r.change < 0 ? 'price-down' : 'price-up'}">${formatPrice(r.change)}</td>
1117 <td class="${r.change < 0 ? 'price-down' : 'price-up'}">${r.percentChange}%</td>
1118 </tr>
1119 `).join('')}
1120 </tbody>
1121 </table>`
1122 }
1123 </div>
1124 </div>
1125 `;
1126
1127 document.body.appendChild(modal);
1128
1129 modal.querySelector('.wpt-close').addEventListener('click', () => modal.remove());
1130 modal.addEventListener('click', (e) => {
1131 if (e.target === modal) modal.remove();
1132 });
1133 }
1134
1135 function addStyles() {
1136 const styles = `
1137 #walmart-power-tools-fab {
1138 position: fixed;
1139 bottom: 20px;
1140 right: 20px;
1141 width: 60px;
1142 height: 60px;
1143 border-radius: 50%;
1144 background: linear-gradient(135deg, #0071ce 0%, #004f9a 100%);
1145 color: white;
1146 border: none;
1147 font-size: 24px;
1148 cursor: pointer;
1149 box-shadow: 0 4px 12px rgba(0, 113, 206, 0.4);
1150 z-index: 999999;
1151 transition: all 0.3s ease;
1152 }
1153
1154 #walmart-power-tools-fab:hover {
1155 transform: scale(1.1);
1156 box-shadow: 0 6px 20px rgba(0, 113, 206, 0.6);
1157 }
1158
1159 #walmart-power-tools-panel {
1160 position: fixed;
1161 top: 50%;
1162 right: 20px;
1163 transform: translateY(-50%);
1164 width: 320px;
1165 max-height: 80vh;
1166 background: white;
1167 border-radius: 12px;
1168 box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
1169 z-index: 999998;
1170 overflow: hidden;
1171 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1172 }
1173
1174 .wpt-header {
1175 background: linear-gradient(135deg, #0071ce 0%, #004f9a 100%);
1176 color: white;
1177 padding: 16px;
1178 display: flex;
1179 justify-content: space-between;
1180 align-items: center;
1181 }
1182
1183 .wpt-header h3 {
1184 margin: 0;
1185 font-size: 16px;
1186 font-weight: 600;
1187 }
1188
1189 .wpt-close {
1190 background: none;
1191 border: none;
1192 color: white;
1193 font-size: 28px;
1194 cursor: pointer;
1195 padding: 0;
1196 width: 30px;
1197 height: 30px;
1198 display: flex;
1199 align-items: center;
1200 justify-content: center;
1201 border-radius: 4px;
1202 transition: background 0.2s;
1203 }
1204
1205 .wpt-close:hover {
1206 background: rgba(255, 255, 255, 0.2);
1207 }
1208
1209 .wpt-content {
1210 padding: 16px;
1211 max-height: calc(80vh - 60px);
1212 overflow-y: auto;
1213 }
1214
1215 .wpt-section {
1216 margin-bottom: 20px;
1217 }
1218
1219 .wpt-section h4 {
1220 margin: 0 0 10px 0;
1221 font-size: 14px;
1222 color: #333;
1223 font-weight: 600;
1224 }
1225
1226 .wpt-btn {
1227 width: 100%;
1228 padding: 10px;
1229 margin-bottom: 8px;
1230 background: #0071ce;
1231 color: white;
1232 border: none;
1233 border-radius: 6px;
1234 cursor: pointer;
1235 font-size: 13px;
1236 font-weight: 500;
1237 transition: all 0.2s;
1238 }
1239
1240 .wpt-btn:hover {
1241 background: #004f9a;
1242 transform: translateY(-1px);
1243 box-shadow: 0 2px 8px rgba(0, 113, 206, 0.3);
1244 }
1245
1246 .wpt-btn:active {
1247 transform: translateY(0);
1248 }
1249
1250 .wpt-btn-small {
1251 padding: 6px 12px;
1252 background: #0071ce;
1253 color: white;
1254 border: none;
1255 border-radius: 4px;
1256 cursor: pointer;
1257 font-size: 12px;
1258 transition: background 0.2s;
1259 }
1260
1261 .wpt-btn-small:hover {
1262 background: #004f9a;
1263 }
1264
1265 .wpt-notification {
1266 position: fixed;
1267 top: 20px;
1268 right: 20px;
1269 padding: 16px 24px;
1270 background: white;
1271 border-radius: 8px;
1272 box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
1273 z-index: 1000000;
1274 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1275 font-size: 14px;
1276 transition: opacity 0.3s;
1277 max-width: 300px;
1278 }
1279
1280 .wpt-notification-success {
1281 border-left: 4px solid #10b981;
1282 color: #065f46;
1283 }
1284
1285 .wpt-notification-error {
1286 border-left: 4px solid #ef4444;
1287 color: #991b1b;
1288 }
1289
1290 .wpt-notification-info {
1291 border-left: 4px solid #0071ce;
1292 color: #1e3a8a;
1293 }
1294
1295 .wpt-modal {
1296 position: fixed;
1297 top: 0;
1298 left: 0;
1299 width: 100%;
1300 height: 100%;
1301 background: rgba(0, 0, 0, 0.5);
1302 display: flex;
1303 align-items: center;
1304 justify-content: center;
1305 z-index: 1000001;
1306 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1307 }
1308
1309 .wpt-modal-content {
1310 background: white;
1311 border-radius: 12px;
1312 width: 90%;
1313 max-width: 600px;
1314 max-height: 80vh;
1315 overflow: hidden;
1316 display: flex;
1317 flex-direction: column;
1318 }
1319
1320 .wpt-modal-large {
1321 max-width: 900px;
1322 }
1323
1324 .wpt-modal-header {
1325 background: linear-gradient(135deg, #0071ce 0%, #004f9a 100%);
1326 color: white;
1327 padding: 16px 20px;
1328 display: flex;
1329 justify-content: space-between;
1330 align-items: center;
1331 }
1332
1333 .wpt-modal-header h3 {
1334 margin: 0;
1335 font-size: 18px;
1336 font-weight: 600;
1337 }
1338
1339 .wpt-modal-body {
1340 padding: 20px;
1341 overflow-y: auto;
1342 }
1343
1344 .wpt-modal-body h4 {
1345 margin-top: 20px;
1346 margin-bottom: 10px;
1347 color: #0071ce;
1348 }
1349
1350 .wpt-modal-body pre {
1351 background: #f3f4f6;
1352 padding: 12px;
1353 border-radius: 6px;
1354 overflow-x: auto;
1355 font-size: 12px;
1356 }
1357
1358 .wpt-tracked-item {
1359 padding: 12px;
1360 border: 1px solid #e5e7eb;
1361 border-radius: 8px;
1362 margin-bottom: 12px;
1363 display: flex;
1364 justify-content: space-between;
1365 align-items: center;
1366 }
1367
1368 .wpt-tracked-info {
1369 flex: 1;
1370 }
1371
1372 .wpt-tracked-info strong {
1373 display: block;
1374 margin-bottom: 4px;
1375 color: #111827;
1376 }
1377
1378 .wpt-tracked-info div {
1379 font-size: 12px;
1380 color: #6b7280;
1381 margin-bottom: 2px;
1382 }
1383
1384 .wpt-price-history {
1385 display: flex;
1386 flex-direction: column;
1387 gap: 8px;
1388 }
1389
1390 .wpt-history-item {
1391 display: flex;
1392 justify-content: space-between;
1393 padding: 10px;
1394 background: #f9fafb;
1395 border-radius: 6px;
1396 }
1397
1398 .wpt-history-price {
1399 font-weight: 600;
1400 color: #0071ce;
1401 }
1402
1403 .wpt-history-date {
1404 font-size: 12px;
1405 color: #6b7280;
1406 }
1407
1408 .wpt-ai-result {
1409 line-height: 1.6;
1410 color: #374151;
1411 }
1412
1413 .wpt-price-table {
1414 width: 100%;
1415 border-collapse: collapse;
1416 }
1417
1418 .wpt-price-table th,
1419 .wpt-price-table td {
1420 padding: 10px;
1421 text-align: left;
1422 border-bottom: 1px solid #e5e7eb;
1423 }
1424
1425 .wpt-price-table th {
1426 background: #f3f4f6;
1427 font-weight: 600;
1428 color: #374151;
1429 }
1430
1431 .price-down {
1432 color: #10b981;
1433 font-weight: 600;
1434 }
1435
1436 .price-up {
1437 color: #ef4444;
1438 font-weight: 600;
1439 }
1440 `;
1441
1442 const styleSheet = document.createElement('style');
1443 styleSheet.textContent = styles;
1444 document.head.appendChild(styleSheet);
1445 }
1446
1447 // ============================================
1448 // KEYBOARD SHORTCUTS
1449 // ============================================
1450
1451 function setupKeyboardShortcuts() {
1452 document.addEventListener('keydown', (e) => {
1453 // Ctrl+Shift+E - Export data
1454 if (e.ctrlKey && e.shiftKey && e.key === 'E') {
1455 e.preventDefault();
1456 const data = extractProductData();
1457 downloadJSON(data, `walmart-products-${Date.now()}.json`);
1458 showNotification('Exported data!', 'success');
1459 }
1460
1461 // Ctrl+Shift+T - Track price
1462 if (e.ctrlKey && e.shiftKey && e.key === 'T') {
1463 e.preventDefault();
1464 trackCurrentProduct();
1465 }
1466
1467 // Ctrl+Shift+P - Toggle panel
1468 if (e.ctrlKey && e.shiftKey && e.key === 'P') {
1469 e.preventDefault();
1470 const panel = document.getElementById('walmart-power-tools-panel');
1471 if (panel) {
1472 panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
1473 } else {
1474 createControlPanel();
1475 }
1476 }
1477
1478 // Ctrl+Shift+A - AI Analysis
1479 if (e.ctrlKey && e.shiftKey && e.key === 'A') {
1480 e.preventDefault();
1481 const product = extractSingleProduct();
1482 if (product) {
1483 aiAnalyzeProduct(product).then(analysis => {
1484 showAIResultModal('AI Product Analysis', analysis);
1485 });
1486 }
1487 }
1488 });
1489 }
1490
1491 // ============================================
1492 // INITIALIZATION
1493 // ============================================
1494
1495 function init() {
1496 console.log('Walmart Power Tools Pro initialized');
1497
1498 addStyles();
1499
1500 setTimeout(() => {
1501 createFloatingButton();
1502 }, 1000);
1503
1504 setupKeyboardShortcuts();
1505
1506 if (window.location.pathname.includes('/ip/')) {
1507 setTimeout(async () => {
1508 const autoTrack = await GM.getValue('auto_track_enabled', false);
1509 if (autoTrack) {
1510 trackCurrentProduct();
1511 }
1512 }, 2000);
1513 }
1514 }
1515
1516 if (document.readyState === 'loading') {
1517 document.addEventListener('DOMContentLoaded', init);
1518 } else {
1519 init();
1520 }
1521
1522})();