Amazon Delivery Status Monitor

Monitor delivery status changes on Amazon tracking pages and send notifications

Versión del día 31/10/2025. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Amazon Delivery Status Monitor
// @version      1.9
// @description  Monitor delivery status changes on Amazon tracking pages and send notifications
// @author       incognico
// @namespace    https://greasyfork.org/users/931787
// @license      MIT
// @match        https://www.amazon.*/gp/your-account/ship-track*
// @match        https://amazon.*/gp/your-account/ship-track*
// @match        https://www.amazon.*/progress-tracker/*
// @match        https://amazon.*/progress-tracker/*
// @icon         https://i.imgur.com/LGHKHEs.png
// @grant        GM_notification
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    console.log('Amazon Delivery Status Monitor loaded');

    const STORAGE_KEY_PREFIX = 'amazon_delivery_status_monitor_';
    let observer = null;
    let refreshTimer = null;
    let isInitialized = false;

    function getItemId() {
        const urlParams = new URLSearchParams(window.location.search);
        return urlParams.get('itemId');
    }

    function getStorageKey() {
        const itemId = getItemId();
        if (!itemId) {
            console.warn('No itemId found in URL');
            return null;
        }
        return STORAGE_KEY_PREFIX + itemId;
    }

    function getStoredStatus() {
        try {
            const storageKey = getStorageKey();
            if (!storageKey) return {};

            const stored = localStorage.getItem(storageKey);
            return stored ? JSON.parse(stored) : {};
        } catch (e) {
            console.warn('Failed to read from localStorage:', e);
            return {};
        }
    }

    function setStoredStatus(statusObj) {
        try {
            const storageKey = getStorageKey();
            if (!storageKey) {
                console.warn('Cannot store status: no itemId found');
                return;
            }

            localStorage.setItem(storageKey, JSON.stringify(statusObj));
        } catch (e) {
            console.warn('Failed to write to localStorage:', e);
        }
    }

    function checkDeliveryStatus() {
        const itemId = getItemId();
        if (!itemId) {
            console.log('No itemId in URL, skipping status check');
            return;
        }

        const elements = {
            outForDelivery: document.querySelector('.H_ib_content'),
            promiseDate: document.querySelector('.pt-promise-main-slot'),
            promiseDetails: document.querySelector('.pt-promise-details-slot'),
            primaryStatus: document.querySelector('#primaryStatus'),
            exceptionMessage: document.querySelector('#lexicalExceptionMessage-container h3') || document.querySelector('.lexicalExceptionMessage-container h3'),
            mainStatus: document.querySelector('.pt-status-main-status'),
            secondaryStatus: document.querySelector('.pt-status-secondary-status')
        };

        const currentStatus = {};
        let hasAnyContent = false;

        // Collect current status from all elements
        Object.keys(elements).forEach(key => {
            const element = elements[key];
            if (element) {
                const content = element.textContent.trim();
                if (content) {
                    currentStatus[key] = content;
                    hasAnyContent = true;
                }
            }
        });

        if (!hasAnyContent) {
            console.log(`No delivery status elements found for item ${itemId}`);
            return;
        }

        const lastStatus = getStoredStatus();
        console.log(`Current delivery status for item ${itemId}:`, currentStatus);

        // Initialize on first run
        if (Object.keys(lastStatus).length === 0) {
            setStoredStatus(currentStatus);
            console.log(`Initial delivery status stored for item ${itemId}:`, currentStatus);
            isInitialized = true;
            setupAutoRefresh(currentStatus);
            return;
        }

        // On page reload, wait a bit before comparing to avoid false "none" notifications
        if (!isInitialized) {
            setStoredStatus(currentStatus);
            console.log(`Status reloaded for item ${itemId}:`, currentStatus);
            isInitialized = true;
            setupAutoRefresh(currentStatus);
            return;
        }

        // Check for changes in any status element
        const changes = [];
        Object.keys(currentStatus).forEach(key => {
            if (currentStatus[key] !== lastStatus[key]) {
                changes.push({
                    field: key,
                    from: lastStatus[key] || 'none',
                    to: currentStatus[key]
                });
            }
        });

        // Check for removed status elements
        Object.keys(lastStatus).forEach(key => {
            if (!currentStatus[key] && lastStatus[key]) {
                changes.push({
                    field: key,
                    from: lastStatus[key],
                    to: 'none'
                });
            }
        });

        if (changes.length > 0) {
            console.log(`Delivery status changes detected for item ${itemId}:`, changes);

            // Check for delivery completion (next stop -> none)
            const deliveryCompletionChange = changes.find(change =>
                change.field === 'outForDelivery' &&
                change.from &&
                change.from.toLowerCase().includes('next stop') &&
                change.to === 'none'
            );

            // Send notification for each change
            changes.forEach(change => {
                const fieldNames = {
                    outForDelivery: 'Out for Delivery',
                    promiseDate: 'Promise Date',
                    promiseDetails: 'Promise Details',
                    primaryStatus: 'Primary Status',
                    exceptionMessage: 'Exception Message',
                    mainStatus: 'Main Status',
                    secondaryStatus: 'Secondary Status'
                };

                const shortItemId = itemId.substring(0, 8) + '...';
                GM_notification({
                    title: `Amazon ${fieldNames[change.field]} Update`,
                    text: `[${shortItemId}] ${fieldNames[change.field]}: ${change.to}`,
                    image: 'https://www.amazon.de/favicon.ico',
                    timeout: 5000,
                    onclick: function() {
                        window.focus();
                    }
                });
            });

            // Store the new status
            setStoredStatus(currentStatus);

            // If delivery was completed (next stop -> none), refresh page after a short delay
            if (deliveryCompletionChange) {
                console.log(`Delivery completed for item ${itemId}, refreshing page in 5 seconds to update tracking info...`);
                setTimeout(() => {
                    window.location.reload();
                }, 5000);
            } else {
                // Update auto-refresh based on new status (only if not doing delivery completion refresh)
                setupAutoRefresh(currentStatus);
            }
        }
    }

    function setupAutoRefresh(currentStatus) {
        // Clear existing timer
        if (refreshTimer) {
            clearInterval(refreshTimer);
            refreshTimer = null;
        }

        // Check if currently out for delivery
        const isOutForDelivery = currentStatus.outForDelivery &&
                                currentStatus.outForDelivery.toLowerCase().includes('stop');

        if (!isOutForDelivery) {
            console.log(`Setting up auto-refresh every 10 minutes for item ${getItemId()}`);
            refreshTimer = setInterval(() => {
                console.log(`Auto-refreshing page for item ${getItemId()}`);
                window.location.reload();
            }, 10 * 60 * 1000); // 10 minutes
        } else {
            console.log(`Package is out for delivery, no auto-refresh needed for item ${getItemId()}`);
        }
    }

    function startMonitoring() {
        // Wait a bit for the page to fully load before initial check
        setTimeout(() => {
            checkDeliveryStatus();
        }, 2000);

        // Set up MutationObserver to watch for changes
        observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                // Check if the delivery status element was affected
                if (mutation.type === 'childList' || mutation.type === 'characterData') {
                    // Only check after initialization to avoid false notifications
                    if (isInitialized) {
                        checkDeliveryStatus();
                    }
                }
            });
        });

        // Start observing the document for changes
        observer.observe(document.body, {
            childList: true,
            subtree: true,
            characterData: true
        });

        console.log('Started monitoring delivery status changes');
    }

    function stopMonitoring() {
        if (observer) {
            observer.disconnect();
            observer = null;
            console.log('Stopped monitoring delivery status changes');
        }

        if (refreshTimer) {
            clearInterval(refreshTimer);
            refreshTimer = null;
            console.log('Stopped auto-refresh timer');
        }
    }

    // Start monitoring when the page is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', startMonitoring);
    } else {
        startMonitoring();
    }

    // Clean up when leaving the page
    window.addEventListener('beforeunload', stopMonitoring);

    // Also check periodically in case MutationObserver misses something
    setInterval(checkDeliveryStatus, 10000); // Check every 10 seconds

})();