Triggered Email Issue for Custom Price Quote Form

Hello,

Wanted to see if anyone has experience with Triggered Emails and has some suggestions or what I am missing.

Basically, I am stuck on triggering an email for a custom price quote form that I created. I have checked all the documentation and a large amount of forum posts. I have tried for hours to rework my code but no luck.

Would someone be able to point me in the right direction on what I have done wrong or am missing? Here is a stripped-down version of my code to save on post length (with less inputs etc.)

import wixData from 'wix-data';
import { contacts } from 'wix-crm';
import { triggeredEmails } from 'wix-crm';

//Does the quote calculation using number input fields
$w.onReady(function () {
$w("#numberRegular").onChange(Price);
$w("#numberSmall").onChange(Price);

});

//Declares price for each input
function Price() {
let regularPrice = 100
let smallPrice = 71

//Declares input name so they can be calculated easier
let Regular = $w('#numberRegular').value 
let Small =  $w('#numberSmall').value

//Calculates how many chosen by price defined above and displays it in an another input field. Works great!
$w("#priceTotal").value = (Regular * regularPrice) + (Small * smallPrice);

}

//Inserts form values into database after Submit button is clicked works great.
export function submit_click(event) {
let quote = {
"regular": $w("#numberRegular").value, 
"small": $w("#numberSmall").value,
"name": $w("#name").value,
"lastName": $w("#name").value,
"email": $w("#email").value,
"phoneNumber": $w("#phone").value,
"address": $w("#address").value,
"price": $w("#priceTotal").value,
  };
  
  wixData.insert("QuoteCollection", quote)
  
//Clears form fields immediately after
    $w("#numberRegular").value = '';
    $w('#name').value = '';
    $w('#lastName').value = '';
    $w("#numberSmall").value ='';
    $w("#description").value ='';
    $w("#email").value ='';
    $w("#phone").value ='';
    $w("#address").value ='';
    $w("#priceTotal").value ='';

//Resets form fields so they aren't in an error state from being cleared
    $w("#numberRegular").resetValidityIndication();
    $w('#name').resetValidityIndication();
    $w('#lastName').resetValidityIndication();
    $w("#numberSmall").resetValidityIndication();
    $w("#description").resetValidityIndication();
    $w("#email").resetValidityIndication();
    $w("#phone").resetValidityIndication();
    $w("#address").resetValidityIndication();
    $w("#priceTotal").resetValidityIndication();
    
//Supposed to create a new contact then send triggered email - This is where I am having trouble
 const contactInfo = {
  name: { first: $w("#name").value , last: $w("#lastName").value},
  emails: [ { email: $w("#email").value } ]

};
contacts.appendOrCreateContact(contactInfo)
.then((result) => {
  let contactId = result.contactId
  console.log(contactId, "this is the contact ID")
triggeredEmails.emailContact('TriggeredEmailQuote', contactId, {

 //These are the variables in the triggered email I have setup already 
  variables: {
    TotalPrice: $w("#priceTotal").value,
    Description: $w("#description").value,
    Regular: $w("#numberRegular").value,
    Small: $w("#numberSmall").value
  }
})
 .then(() => {

  })
  .catch((err) => {
    console.log(err)
  });
  });
}    

Here are the errors I am getting from my console Logs.

The quote calculator works great and shows the price based on the numbered inputs. It adds everything to the collection after the submit button, however it does not create a new contact and does not send the triggered email. Any help would be incredibly appreciated. I was thinking I am missing an afterInsert or something but not sure what.

Thanks in advance!

I would try to run the create contact in the backend and to print the contact info before the create to make sure it is correct.
Why do you empty the fields before creating the contact? try to do it after if you need to

Thank you so much!

Apparently, I was having one of those days, because as soon as I moved the clear function to the then statement it all worked perfectly. What a silly mistake on my end. Really appreciate you catching that for me!

Here is the working code if anyone needs it.

import wixData from 'wix-data';
import { contacts } from 'wix-crm';
import { triggeredEmails } from 'wix-crm';

//Does the quote calculation using number input fields
$w.onReady(function () {
$w("#numberRegular").onChange(Price);
$w("#numberSmall").onChange(Price);

});

//Declares price for each input
function Price() {
let regularPrice = 100
let smallPrice = 71

//Declares input name so they can be calculated easier
let Regular = $w('#numberRegular').value 
let Small =  $w('#numberSmall').value

//Calculates how many chosen by price defined above and displays it in an another input field. Works great!
$w("#priceTotal").value = (Regular * regularPrice) + (Small * smallPrice);

}

//Inserts form values into database after Submit button is clicked works great.
export function submit_click(event) {
let quote = {
"regular": $w("#numberRegular").value, 
"small": $w("#numberSmall").value,
"name": $w("#name").value,
"lastName": $w("#name").value,
"email": $w("#email").value,
"phoneNumber": $w("#phone").value,
"address": $w("#address").value,
"price": $w("#priceTotal").value,
  };
  
  wixData.insert("QuoteCollection", quote)
  
    
//Creates a new contact then send triggered email
 const contactInfo = {
  name: { first: $w("#name").value , last: $w("#lastName").value},
  emails: [ { email: $w("#email").value } ]

};
contacts.appendOrCreateContact(contactInfo)
.then((result) => {
  let contactId = result.contactId
  console.log(contactId, "this is the contact ID")
triggeredEmails.emailContact('TriggeredEmailQuote', contactId, {

 //These are the variables in the triggered email I have setup already 
  variables: {
    TotalPrice: $w("#priceTotal").value,
    Description: $w("#description").value,
    Regular: $w("#numberRegular").value,
    Small: $w("#numberSmall").value
  }
})
 .then(() => {
     //Clears form fields immediately after
    $w("#numberRegular").value = '';
    $w('#name').value = '';
    $w('#lastName').value = '';
    $w("#numberSmall").value ='';
    $w("#description").value ='';
    $w("#email").value ='';
    $w("#phone").value ='';
    $w("#address").value ='';
    $w("#priceTotal").value ='';

//Resets form fields so they aren't in an error state from being cleared
    $w("#numberRegular").resetValidityIndication();
    $w('#name').resetValidityIndication();
    $w('#lastName').resetValidityIndication();
    $w("#numberSmall").resetValidityIndication();
    $w("#description").resetValidityIndication();
    $w("#email").resetValidityIndication();
    $w("#phone").resetValidityIndication();
    $w("#address").resetValidityIndication();
    $w("#priceTotal").resetValidityIndication();

  })
  .catch((err) => {
    console.log(err)
  });
  });
}    

Hey @guy-tadmor This has been working but now I am getting some odd issues with the contactId. Do you have an example or know how I would run the create contact from the backend? Not sure how to do that with inputs from the front end.

What kind of issues do u have?

Hey @guy-tadmor thanks for the response! I really appreciate it. I am having a few issues. The first which has taken me the most amount of time is I cannot find a way to send a triggered email to two contacts at the same time. As I want to notify the person filling out the form as well as get notified every time someone requests a quote. I have two separate triggered emails setup, but it will only allow me to send one of them. As it gives me “contactId does not match current session contact (401)”

I am also having an issue with the website caching the contactId. It’s essentially storing the contactId somewhere and now no longer works giving me the same “contactId does not match current session contact (401)” but for a different contact then the new one I am now entering. For ex.

if Email Address 1 is contactId 12345
Then I enter a new email address it still says the contactId is 12345 and gives the error when the new contact should be a totally different id. This use to work perfectly now for some reason is stuck.

Not sure if you can help me with this but any advice would be greatly appreciated. Thanks so much!

I believe that if you use backend code you will not have issues with the cache as in the page code the API send the email only for the current contact.

Here is the code:

Page code:

import { createMyContact } from ‘backend/myContacts.jsw’

/**

  • Adds an event handler that runs when the element is clicked.
    Read more
  • @param {$w.MouseEvent} event
    */
    export async function button1_click ( event ) {
    // This function was added from the Properties & Events panel. To learn more, visit Velo: Working with the Properties & Events Panel | Help Center | Wix.com
    // Add your code for this event here:
    let fname = $w ( “#inputFname” ). value ;
    let lname = $w ( “#inputLname” ). value ;
    let email = $w ( “#inputEmail” ). value ;
    let phone = $w ( “#inputPhone” ). value ;
    try {
    let response = await createMyContact ( fname , lname , email , phone );
    } catch ( err ) {
    console . log ( err );
    }
    }

Backend code in myCotnacts.jsw:

/*********
.jsw file


Backend .jsw files contain functions that run on the server side but can be called from page code and frontend files.
Use backend functions to keep code private and hidden from a user’s browser. More info:

Velo Web Modules: Calling Backend Code from the Frontend | Help Center | Wix.com

**********/

import { contacts } from ‘wix-crm-backend’ ;

export async function createMyContact ( fname , lname , email , phone ) {
// This function was added from the Properties & Events panel. To learn more, visit Velo: Working with the Properties & Events Panel | Help Center | Wix.com
// Add your code for this event here:

**return**  **new**  Promise (( resolve ,  reject ) => { 

    const  contactInfo  = { 
        name : { 
            first :  fname , 
            last :  lname 
        }, 
        emails : [{ 
            email :  email , 
        }], 
        phones : [{ 
            tag :  "MOBILE" , 
            phone :  phone , 
            primary :  **true** 
        }] 

    }; 
    // when the email/phone given exists (can be only one of them), the mobile phone or email is added to the same contact. 
    contacts . appendOrCreateContact ( contactInfo ) 
        . then (( resolvedContact ) => { 
            console . log ( JSON . stringify ( resolvedContact )); 
            // TODO add fname and lname 
            sendEmail ( resolvedContact . contactId ,  fname ,  lname , 'TP21do9' ); 
            resolve ( resolvedContact . contactId ) 


        }) 
        . catch (( error ) => { 
            console . error ( "createContact error = "  +  JSON . stringify ( error )); 
            if  ( error . details . applicationError . code  ==  "DUPLICATE_CONTACT_EXISTS" ) { 
                console . log ( "duplicate contact" ); 
            } 
            reject ( error ); 

        }); 
}) 

}

import { triggeredEmails } from ‘wix-crm-backend’ ;

function sendEmail ( contactId , fname , lname , emailCode ) {

triggeredEmails . emailContact ( emailCode ,  contactId , { 
        variables : { 
            fname :  fname , 
            lname :  lname                 
        } 
    }) 
    . then (() => { 
        console . log ( 'Email was sent to contact' ); 
    }) 
    . catch (( error ) => { 
        console . error ( "trigger Email error "  +  error ); 
    }); 

}