Campaign to capture user's birthday

Overview

Consumer businesses often send offers to their users on their special days (birthdays, anniversaries etc.,) as they can lead to higher conversions. Marketers can use on-site messaging (OSM) in MoEngage to capture important dates and schedule such campaigns. You can find a sample popup in the below image. 

OSM_Birthday.png

 

info

Information

  • Birthday in MoE is a datetime attribute and not a date attribute. So in dashboard the Birthday will be displayed in as dd mmm yyyy, hh:mm:ss
  • HTML does not support Placeholder text for Date field. So we’ll have to pass the Label separately

Campaign Creation

Follow the steps below to create this campaign:

  1. Create an OSM campaign with trigger criteria that suits your business needs.
  2. Add the below code block in Custom HTML. 

Custom HTML

HTML

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <link rel="stylesheet" type="text/css"
    href="https://fonts.googleapis.com/css?family=ABeeZee|Abel|Aclonica|Acme|Actor|Advent+Pro|Alata|Alatsi|Aldrich|Alef|Alegreya+Sans|Alegreya+Sans+SC|Allerta|Allerta+Stencil|Almarai|Amaranth|Amiko|Anaheim|Andika|Andika+New+Basic|Antic|Anton|Archivo|Archivo+Black|Archivo+Narrow|Arimo|Armata|Arsenal|Arya|Asap|Asap+Condensed|Assistant|Asul|Athiti|Average+Sans|B612|Bai+Jamjuree|Barlow|Barlow+Condensed|Barlow+Semi+Condensed|Basic|Be+Vietnam|Belleza|BenchNine|Biryani|Black+And+White+Picture|Black+Han+Sans|Blinker|Bubbler+One|Cabin|Cabin+Condensed|Cagliostro|Cairo|Cambay|Candal|Cantarell|Cantora+One|Capriola|Carme|Carrois+Gothic|Carrois+Gothic+SC|Catamaran|Chakra+Petch|Changa|Chathura|Chau+Philomene+One|Chivo|Coda+Caption|Commissioner|Convergence|Cuprum|DM+Sans|Darker+Grotesque|Days+One|Denk+One|Dhurjati|Didact+Gothic|Do+Hyeon|Doppio+One|Dorsa|Dosis|Duru+Sans|Economica|El+Messiri|Electrolize|Encode+Sans|Encode+Sans+Condensed|Encode+Sans+Expanded|Encode+Sans+Semi+Condensed|Encode+Sans+Semi+Expanded|Englebert|Epilogue|Exo|Exo+2|Fahkwang|Farro|Federo|Fira+Sans|Fira+Sans+Condensed|Fira+Sans+Extra+Condensed|Fjalla+One|Francois+One|Fresca|GFS+Neohellenic|Gafata|Galdeano|Gayathri|Geo|Gidugu|Gothic+A1|Gotu|Gudea|Hammersmith+One|Harmattan|Heebo|Hind|Hind+Guntur|Hind+Madurai|Hind+Siliguri|Hind+Vadodara|Homenaje|IBM+Plex+Sans|IBM+Plex+Sans+Condensed|Imprima|Inder|Inria+Sans|Inter|Istok+Web|Jaldi|Jockey+One|Josefin+Sans|Jost|Jua|Julius+Sans+One|Jura|K2D|Kanit|Kantumruy|Karla|Khand|Khula|Kite+One|KoHo|Kodchasan|Kosugi|Kosugi+Maru|Krona+One|Krub|Kulim+Park|Kumbh+Sans|Lato|Lekton|Lexend+Deca|Lexend+Exa|Lexend+Giga|Lexend+Mega|Lexend+Peta|Lexend+Tera|Lexend+Zetta|Libre+Franklin|Livvic|M+PLUS+1p|M+PLUS+Rounded+1c|Mada|Magra|Mako|Mallanna|Mandali|Manjari|Manrope|Marmelad|Martel+Sans|Marvel|Maven+Pro|Meera+Inimai|Merriweather+Sans|Metrophobic|Michroma|Mina|Miriam+Libre|Mitr|Molengo|Monda|Montserrat|Montserrat+Alternates|Montserrat+Subrayada|Mouse+Memoirs|Mukta|Mukta+Mahee|Mukta+Malar|Mukta+Vaani|Mulish|NTR|Nanum+Gothic|News+Cycle|Niramit|Nobile|Notable|Noto+Sans|Noto+Sans+HK|Noto+Sans+JP|Noto+Sans+KR|Noto+Sans+SC|Noto+Sans+TC|Numans|Nunito|Nunito+Sans|Open+Sans|Open+Sans+Condensed|Orbitron|Orienta|Oswald|Overpass|Oxygen|PT+Sans|PT+Sans+Caption|PT+Sans+Narrow|Padauk|Palanquin|Palanquin+Dark|Pathway+Gothic+One|Pattaya|Pavanam|Paytone+One|Philosopher|Play|Pontano+Sans|Poppins|Port+Lligat+Sans|Pragati+Narrow|Prompt|Proza+Libre|Public+Sans|Puritan|Quantico|Quattrocento+Sans|Questrial|Quicksand|Rajdhani|Raleway|Ramabhadra|Rambla|Rationale|Recursive|Red+Hat+Display|Red+Hat+Text|Reem+Kufi|Roboto|Roboto+Condensed|Ropa+Sans|Rosario|Rubik|Rubik+Mono+One|Ruda|Ruluko|Rum+Raisin|Russo+One|Saira|Saira+Condensed|Saira+Extra+Condensed|Saira+Semi+Condensed|Sansita|Sarabun|Sarala|Sarpanch|Sawarabi+Gothic|Sawarabi+Mincho|Scada|Secular+One|Sen|Seymour+One|Shanti|Share+Tech|Signika|Signika+Negative|Sintony|Six+Caps|Snippet|Sora|Source+Sans+Pro|Space+Grotesk|Spartan|Spinnaker|Strait|Stylish|Sulphur+Point|Sunflower|Syncopate|Syne|Tajawal|Tauri|Teko|Telex|Tenali+Ramakrishna|Tenor+Sans|Text+Me+One|Thasadith|Timmana|Titillium+Web|Tomorrow|Trispace|Ubuntu|Ubuntu+Condensed|Varela|Varela+Round|Varta|Viga|Voltaire|Wendy+One|Wire+One|Work+Sans|Yanone+Kaffeesatz|Yantramanav">
  <script type="text/javascript">
    (function(i, s, o, g, r, a, m, n) {
      i.moengage_object = r;
      t = {};
      q = function(f) {
        return function() {
          (i.moengage_q = i.moengage_q || []).push({
            f: f,
            a: arguments
          })
        }
      };
      f = ['track_event', 'add_user_attribute', 'add_first_name', 'add_last_name', 'add_email', 'add_mobile', 'add_user_name', 'add_gender', 'add_birthday', 'destroy_session', 'add_unique_user_id', 'moe_events', 'call_web_push', 'track',
        'location_type_attribute'
      ], h = {
        onsite: ["getData", "registerCallback"]
      };
      for (k in f) {
        t[f[k]] = q(f[k])
      }
      for (k in h)
        for (l in h[k]) {
          null == t[k] && (t[k] = {}), t[k][h[k][l]] = q(k + "." + h[k][l])
        }
      a = s.createElement(o);
      m = s.getElementsByTagName(o)[0];
      a.async = 1;
      a.src = g;
      m.parentNode.insertBefore(a, m);
      i.moe = i.moe || function() {
        n = arguments[0];
        return t
      };
      a.onload = function() {
        if (n) {
          i[r] = moe(n)
        }
      }
    })(window, document, 'script', 'https://cdn.moengage.com/webpush/moe_webSdk.min.latest.js', 'Moengage')


    Moengage = moe({
      app_id: "FM6H6BZQGCY4WEUAXTKAYU3X",
      debug_logs: 1
      //  swPath: "https://srimutu.github.io/serviceworker.js"
    });
  </script>


  <style>
    .container {
      background: #ffffff;
      padding: 20px;
      display: inline-block;
      text-align: center;
      width: 340px;
      position: relative;
      border: 1px solid #cccccc;
      max-width: 800px;
      word-break: break-all;
      background-repeat: no-repeat;
      background-size: 100%;
    }

    .flex-v-container {
      display: flex;
      flex-direction: column;
      margin-top: 50px;
    }

    .input-container {
      margin-top: 20px;
      padding: 10px;
      border: 0px solid transparent;
      border-bottom: 1px solid #ccc;
      width: 90%;
    }

    .button-container {
      margin-top: 20px;
      background: #000000;
      color: #ffffff;
      padding: 10px;
      padding-right: 20px;
      padding-left: 20px;
      font-weight: bold;
      font-family: Montserrat;
      font-size: 14px;
      width: 90%;
      cursor: pointer;
    }

    .header {
      font-size: 27px;
      font-family: Montserrat;
      font-weight: bold;
      word-break: break-word;
    }

    .title {
      font-size: 22px;
      font-family: Montserrat;
      word-break: break-word;
    }

    .close-icon {
      position: absolute;
      top: 10px;
      right: 10px;
      border: none;
      font-size: 20px;
      cursor: pointer;
      background: transparent;
    }

    button:focus {
      outline: none;
    }

    input:focus {
      outline: none;
      border-bottom: 1px solid #000000;
    }

    body {
      display: flex;
      flex: 1;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      background-repeat: no-repeat;
    }

    @media only screen and (max-width: 600px) {
      .container {
        width: 100%;
        background-size: 100%;
        margin: 10px;
        /* background-position: center center; */

      }

      .lead-gen-container {
        min-width: 300px;
      }
    }

    .moe-error {
      border: 1px solid #ec4b39;
    }

    .moe-error-text.invisible {
      display: none;
    }

    .moe-error-text {
      color: red;
      font-size: 12px;
      margin-top: 1px;
    }
  </style>

</head>

<body data-editor-type="MOE_EDITOR" data-template-type="LEAD_GEN">
  <!-- The external link on href is not found to be working in browsers of some iPhone models, please use onclick as an alternative that works for all platforms
	 For example,
	 instead of: <a href="url" target="_blank"> Link text </a>
	 use: <a onclick="window.open('url', '_blank')"> Link text </a>
    -->
  <div style="display: flex; justify-content: center; position: relative;" class="lead-gen-container">
    <div class="container moe-container moe-element" data-id="CONTAINER">
      <div class="no-bounds">
        <p class="header moe-element" data-id="HEADER1">SIGN UP NOW FOR YOUR 15% OFF</p>
        <p class="title moe-element" data-id="HEADER2">And get immediate access to our latest offers!</p>
      </div>
      <div class="flex-v-container no-bounds">
        <input placeholder="First Name" class="input-container moe-element" data-id="INPUT1" id="TEXT_INPUT_1" data-user="u_fn" />
        <input placeholder="Email Address" class="input-container moe-element" data-id="INPUT2" id="TEXT_INPUT_2" data-user="u_em" data-input-validation-type="email" required />
        <h6 style="text-align: left;padding-bottom: 0px;margin-bottom: 0px;color: gray;margin-left: 10px;font-size: 14px;font-weight: 500;"> Enter Date of Birth </h6>
        <input placeholder="DOB" class="input-container moe-element" type="date" data-id="INPUT3" id="TEXT_INPUT_3" data-user="u_bd" required style="margin-top: 0px;"/>
      </div>
      <div class="no-bounds" style="display: flex;">
        <span class="button-container moe-element" id="lead-gen-submit" data-id="SUBMIT">Subscribe Now</span>
      </div>


    </div>
  </div>

  <script>
    const buttonElem = document.getElementById('lead-gen-submit');
    const inputElement = document.getElementById('TEXT_INPUT_1');
    const inputElement1 = document.getElementById('TEXT_INPUT_2');
    const dateOFBirth = document.getElementById('TEXT_INPUT_3'); // DOB

    buttonElem.disabled = true;

    function removeError(targetElement) {
      const nextSiblings = targetElement.nextElementSibling;
      if (targetElement && targetElement.classList.contains("moe-error")) {
        targetElement.classList.remove("moe-error");
      }
      if (nextSiblings) {
        nextSiblings.classList.add('invisible');
      }
    }

    function addError(targetElement, validationMsg) {
      const nextSiblings = targetElement.nextElementSibling;
      targetElement.classList.add("moe-error");
      if (nextSiblings && nextSiblings.classList.contains('invisible')) {
        nextSiblings.classList.remove('invisible');
      }
      if (nextSiblings && validationMsg) {
        nextSiblings.textContent = validationMsg;
      }
    }

    function isEmailAddressValid(email) {
      const emailRegex =
        /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
      return emailRegex.test(String(email.trim()).toLowerCase());
    }

    function isFormDataValid() {
      let isFormValid = true;
      const inputElements = document.querySelectorAll("input");
      for (let i = 0; i < inputElements.length; i++) {
        let validationMsg;
        let isValid = true;
        if (
          inputElements[i].hasAttribute("required") &&
          !inputElements[i].value
        ) {
          isValid = false;
          validationMsg = 'This field is required';
        }
        // email validation
        if (isValid && inputElements[i].dataset.inputValidationType === "email") {
          if (!isEmailAddressValid(inputElements[i].value)) {
            isValid = false;
            validationMsg = 'Please enter valid email address';
          }
        }

        if (!isValid) {
          addError(inputElements[i], validationMsg);
          isFormValid = false;
        } else {
          removeError(inputElements[i]);
        }
      }
      return isFormValid;
    }

    function submitLeadgenData(targetElement) {
      const isMoeInAppCloseBtnAvailable = targetElement && targetElement.classList.contains("moe-inapp-close");
      const isMoeInAppClickBtnAvailable = targetElement && targetElement.classList.contains('moe-inapp-click');
      if (!isFormDataValid()) {
        // remove moe-inapp-close class to prevent popup close
        if (isMoeInAppCloseBtnAvailable) {
          targetElement.classList.remove("moe-inapp-close");
        }
        // remove moe-inapp-click class to prevent click tracking
        if (isMoeInAppClickBtnAvailable) {
          targetElement.classList.remove("moe-inapp-click");
        }
        return false;
      }
      if (!isMoeInAppCloseBtnAvailable) {
        targetElement.classList.add("moe-inapp-close");
      }
      if (!isMoeInAppClickBtnAvailable) {
        targetElement.classList.add('moe-inapp-click');
      }
      const ATTR_MAP = {
        uid: "USER_ATTRIBUTE_UNIQUE_ID",
        u_em: "USER_ATTRIBUTE_USER_EMAIL",
        u_mb: "USER_ATTRIBUTE_USER_MOBILE",
        u_fn: "USER_ATTRIBUTE_USER_FIRST_NAME",
        u_ln: "USER_ATTRIBUTE_USER_LAST_NAME",
        u_n: "USER_ATTRIBUTE_USER_NAME",
        u_gd: "USER_ATTRIBUTE_USER_GENDER",
        u_bd: "USER_ATTRIBUTE_USER_BDAY",
      };
      const attributeObj = {};
      const inputElements = document.querySelectorAll("input");
      for (let i = 0; i < inputElements.length; i++) {
        const inputElement = inputElements[i];
        if (inputElement.style.display !== "none") {
          const userAttribute = ATTR_MAP[inputElement.dataset.user] || inputElement.dataset.user;
          window.parent.Moengage.add_user_attribute(userAttribute, inputElement.value);
          attributeObj[userAttribute] = inputElement.value;
          console.log((userAttribute, inputElement.value));
        }
      }
      const birthDate = new Date(dateOFBirth.value);
      const bDate = birthDate.getDate();
      const bMonth = birthDate.getMonth();
      const bYear = birthDate.getFullYear();
      window.parent.Moengage.add_birthday(new Date(bYear, bMonth, bDate));
      window.parent.Moengage.add_user_attribute("ATTRIBUTE_NAME_4", new Date(birthDate.getFullYear(), birthDate.getMonth(), birthDate.getDate())); //custom attri


      window.parent.Moengage.track_event("MOE_RESPONSE_SUBMITTED", attributeObj);


    }

    function enableButton() {
      if (inputElement.style.display !== 'none' && inputElement1.style.display !== 'none') {
        if (inputElement.value.length && inputElement1.value.length) {
          buttonElem.disabled = false;
        }
      } else if (inputElement.style.display !== 'none') {
        if (inputElement.value.length) {
          buttonElem.disabled = false;
        }
      } else if (inputElement1.style.display !== 'none') {
        if (inputElement1.value.length) {
          buttonElem.disabled = false;
        }
      }
    }

    inputElement.addEventListener('input', (event) => {
      enableButton();
    });

    inputElement1.addEventListener('input', (event) => {
      enableButton();
    });

    document.getElementById('lead-gen-submit').addEventListener('click', (event) => {
      if (window.parent.Moengage) {
        submitLeadgenData(event.target);
      }
    });
  </script>

</body>

</html>

To pass time along with the date attribute, you can use the code below in place of line 312 in the code block mentioned above.

HTML
window.parent.Moengage.add_birthday(new Date(bYear, bMonth, bDate , 13 , 14 , 14 ));
Was this article helpful?
0 out of 0 found this helpful