I am trying to send a webhook when a member update their profile

Hello. I managed to do it.
Below is my original code that works, but the problem is that it sends multiple webhooks at a time.

import { fetch } from 'wix-fetch';

const WEBHOOK_URL = "https://[mysite.com]/webhook/3324dfdfg-73a0-4eb3-a74b";

export function wixMembers_onMemberUpdated(event) {
    // Log the entire event to see what we're receiving
    console.log('Event received:', JSON.stringify(event));
    
    // Extract the basic info
    const payload = {
        contactId: event.entity._id,
        updatedDate: event.entity._updatedDate,
        memberLoginEmail: event.entity.loginEmail,
    };

    console.log('Sending payload:', JSON.stringify(payload));

    // Send webhook
    fetch(WEBHOOK_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
    })
    .then(response => {
        console.log('Response status:', response.status);
        return response.text();
    })
    .then(text => {
        console.log('Response body:', text);
    })
    .catch(error => {
        console.error('Error:', error);
    });

    // Return success response to Wix
    return {
        "status": 200
    };
}

I asked GPT and it gave below suggestion. But still sending mutiple webhook randomly.

import { fetch } from 'wix-fetch';

const WEBHOOK_URL = "https://[mysite.com]/webhook/3324dfdfg-73a0-4eb3-a74b";
const COOLDOWN = 5000; // 5 seconds
let lastWebhookTime = 0;

export function wixMembers_onMemberUpdated(event) {
    const currentTime = Date.now();
    
    // Check if enough time has passed since last webhook
    if (currentTime - lastWebhookTime < COOLDOWN) {
        console.log('Skipping webhook - too soon');
        return { status: 200 };
    }

    // Update last webhook time
    lastWebhookTime = currentTime;

    // Prepare payload
    const payload = {
        contactId: event.entity._id,
        updatedDate: event.entity._updatedDate,
        memberLoginEmail: event.entity.loginEmail
    };

    // Send webhook
    return fetch(WEBHOOK_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
    })
    .then(() => {
        console.log('Webhook sent successfully');
        return { status: 200 };
    })
    .catch(error => {
        console.error('Webhook error:', error);
        return { status: 200 };
    });
}

Any idea how to resolve it?
Thanks!

There are some sections that require you to clicka “save” button and other places that save automatically on keypress.

So, yes, your webhook will get triggered every single time it saves by button press or with every keypress.

What is it that you are trying to achieve with that webhook?

When a user updates their profile, I want to get the contact ID so I can retrieve the member data using the contact ID. Then, I will update the information in my Airtable.

Basically, I am trying to sync my Airtable member information with Wix. Whenever a member updates their profile information, I will update their info in Airtable.

Becuase there is no native trigger (User Profile updated) from Wix automation. So should I do it correctly?

Thanks

I cannot test this, but thought you may be able use a timeout to fire a notification email.

I had chatGPT add this to your existing code and also asked for a failure email if the timeout fails. You may want that bit or not.

import { fetch } from 'wix-fetch';

const WEBHOOK_URL = "https://[mysite.com]/webhook/3324dfdfg-73a0-4eb3-a74b";
const COOLDOWN = 20 * 60 * 1000; // 20 minutes in milliseconds
let storedNotification = null;
let timeoutId = null;
const RETRY_DELAY = 10000; // 10 seconds for retry
let hasRetried = false;

export function wixMembers_onMemberUpdated(event) {
    // Store only the first notification details
    if (!storedNotification) {
        storedNotification = {
            contactId: event.entity._id,
            updatedDate: event.entity._updatedDate,
            memberLoginEmail: event.entity.loginEmail
        };
    }

    // If there's already a timeout running, return early
    if (timeoutId) {
        return { status: 200 };
    }

    // Set a timeout to send the stored notification
    timeoutId = setTimeout(() => {
        sendNotification();
    }, COOLDOWN);

    return { status: 200 };
}

// Function to send the stored notification
function sendNotification() {
    if (!storedNotification) {
        console.log('No notification to send');
        return;
    }

    const payload = storedNotification;

    // Clear the stored notification and timeout ID
    storedNotification = null;
    timeoutId = null;

    // Reset retry flag for new notifications
    hasRetried = false;

    // Send the webhook
    fetch(WEBHOOK_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
    })
    .then(() => {
        console.log('Webhook sent successfully');
    })
    .catch(error => {
        console.error('Webhook error:', error);

        // Retry sending the notification if it hasn't been retried yet
        if (!hasRetried) {
            hasRetried = true;
            console.log(`Retrying in ${RETRY_DELAY / 1000} seconds...`);
            setTimeout(() => retryNotification(payload), RETRY_DELAY);
        }
    });
}

// Retry sending the notification
function retryNotification(payload) {
    fetch(WEBHOOK_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
    })
    .then(() => {
        console.log('Webhook retry sent successfully');
    })
    .catch(error => {
        console.error('Webhook retry failed:', error);
        // Optionally, log or notify of the persistent failure
    });
}

Double check var names etc as chatGPT has a habit of changing things like that without telling you or why.

Sligt update to only retry once if timeout fails.

Hello

Sadly it does not work. Nothing is triggered… By the way do you know Am I using the right function wixMembers_onMemberUpdated? Or there is a more suitable one?

Thanks

I don’t , but I did have look at the API, and that seemed to be the only one.

I just set it up on my test site,

I do not have my own web hook server so I am just using wix’s http-functions.js to pick them up.

This is the latest code, it seems there was a clash in the timer

import { fetch } from 'wix-fetch';

const WEBHOOK_URL = "https://[mysite.com]/webhook/3324dfdfg-73a0-4eb3-a74b";
const COOLDOWN = 20 * 60 * 1000; // 20 minutes in milliseconds
const RETRY_DELAY = 10000; // 10 seconds for retry

let storedNotification = null;
let timeoutId = null;
let retryTimeoutId = null;
let hasRetried = false;

export function wixMembers_onMemberUpdated(event) {
    // Store only the first notification details
    if (!storedNotification) {
        storedNotification = {
            contactId: event.entity._id,
            updatedDate: event.entity._updatedDate,
            memberLoginEmail: event.entity.loginEmail
        };
    }
     console.log('Webhook recieved :', storedNotification);
    // If there's already a timeout running, return early
    if (timeoutId) {
        return { status: 200 };
    }

    // Set a timeout to send the stored notification
    timeoutId = setTimeout(() => {
        sendNotification();
    }, COOLDOWN);

    return { status: 200 };
}

// Function to send the stored notification
function sendNotification() {
    if (!storedNotification) {
        console.log('No notification to send');
        clearTimeout(timeoutId);
        timeoutId = null;
        return;
    }

    const payload = storedNotification;

    // Clear the stored notification and reset timeout IDs
    storedNotification = null;
    timeoutId = null;

    // Reset retry state for new notifications
    hasRetried = false;

    // Send the webhook
    fetch(WEBHOOK_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
    })
    .then(() => {
        console.log('Webhook sent successfully');
    })
    .catch(error => {
        console.error('Webhook error:', error);

        // Retry sending the notification if it hasn't been retried yet
        if (!hasRetried) {
            hasRetried = true;
            retryTimeoutId = setTimeout(() => {
                retryNotification(payload);
            }, RETRY_DELAY);
        }
    });
}

// Retry sending the notification
function retryNotification(payload) {
    fetch(WEBHOOK_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
    })
    .then(() => {
        console.log('Webhook retry sent successfully');
    })
    .catch(error => {
        console.error('Webhook retry failed:', error);
        // No further retries; optionally log the failure
    });
}

My wix’s http-functions.js. function registered the webhook events ok. And then I get the web hook payload. in mine I set it to 2minutes for debugging. I would not set it for less than that, as I did get it firing a lot. below that.

Any way hope this helps.

Note although the logs show the “Webhook sent successfully” from the event.js after the ‘Incoming request body’ & ‘Prepared response body:’ messages from the web hook server (http-functions.js) it was sent before them… just logged out of order.

1 Like