TAC Sleekflow

TAC Sleekflow adalah yang di transfer setiap 3 jam sekali ke database sleekflow yang tidak mempengaruhi TAC Funnel secara langsung.

Push Sleekflow Inbound to TAC Sleekflow

Analytics

TAC Sleekflow

Key Points :

  1. TAC Sleekflow adalah unique data

  2. TAC Sleekflow adalah data yang memiliki phone number maupun tidak memiliki phone number (dari direct message instagram)

  3. TAC Sleekflow adalah data kontak yang ada sejak September 2024 sampai saat ini

  4. TAC Sleekflow akan berbeda dengan TAC Funnel, dikarenakan TAC Sleekflow belum di deduct oleh data existing TAC Funnel

  5. TAC Sleekflow adalah data pembanding TAC Inbound / TAC Inbound

  6. TAC Sleekflow hanya memiliki 2 source : meta_ads dan social_media

HTTP Request

Code

convert.js
// Function to format the timestamp to 'YYYY-MM-DD HH:MM:SS'
function formatTimestamp(timestamp) {
  const date = timestamp ? new Date(timestamp) : new Date(); // Use current date-time if missing

  // Extract the year, month, day, hours, minutes, and seconds
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0'); // Month is 0-based
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

// List of names to check for exclusion
const excludedOwners = new Set([
  'KYZN', 'Diadre Marketing', 'Sales BSD', 'Sales KNG', 
  'Lutfi CA', 'FO BSD', 'FO Kuningan', 'Siska Permata', 'Admin KYZN'
]);

// Function to map sremarks_id to specific labels
function mapSremarksId(sremarks_id) {
  if (!sremarks_id) return "whatsapp"; // Default jika tidak ada id
  
  const identityMap = {
    "409534172246677": "fb_kyzn_id",
    "17841468769957389": "ig_kyzn_id",
    "19190": "fb_kuningan",
    "17841453892878958": "ig_kuningan",
    "19191": "fb_bsd",
    "17841450110322840": "ig_bsd",
    "113207553436200": "ig_kyzn_life",
    "110429021829147": "ig_kyzn_preschool",
    "6285174420088": "whatsapp"
  };

  return identityMap[sremarks_id] || "whatsapp";
}

// Function to determine branch based on sremarks
function mapBranch(sremarks) {
  const branchMapping = {
    fb_bsd: "KYZN BSD",
    ig_bsd: "KYZN BSD",
    fb_kuningan: "KYZN Kuningan",
    ig_kuningan: "KYZN Kuningan"
  };
  return branchMapping[sremarks] || "KYZN"; // Default branch value
}

// Function to determine mremarks based on sremarks
function mapMremarks(sremarks) {
  const dmSources = ["fb_kyzn_id", "ig_kyzn_id", "fb_kuningan", "ig_kuningan", "fb_bsd", "ig_bsd"];
  return dmSources.includes(sremarks) ? "dm" : "wa"; // Default fallback
}

// Function to convert text to Capitalized Case
function capitalizeText(text) {
  if (!text) return null; // Handle missing text
  return text
    .toLowerCase()
    .split(" ")
    .map(word => word.charAt(0).toUpperCase() + word.slice(1))
    .join(" ");
}

// Get the input from the previous node
const data = items;

// Transform the data, converting all relevant timestamp fields
const result = data.map(item => {
  const contactOwnerName = item.json.ContactOwnerName || null;
  const adSourceId = item.json.AdSourceID || null;
  const leadSource = item.json.LeadSource || null;
  const phoneNumber = item.json.PhoneNumber || null;
  const sremarks_id = item.json.sremarks_id || null;

  let source = leadSource;
  let sremarks = item.json.sremarks || null;
  let medium = 'sleekflow'; // Default to 'sleekflow'
  let mremarks = item.json.mremarks || null;

  // Apply conditions
  if (adSourceId) {
    // Jika ad_source_id tidak null
    source = 'meta_ads';
    sremarks = adSourceId;
    mremarks = 'wa';
  } else {
    // Jika ad_source_id null, cek sremarks_id
    sremarks = mapSremarksId(sremarks_id);
    source = 'social_media';
    mremarks = mapMremarks(sremarks);
  }

  return {
    id: item.json.id || null,
    phone: phoneNumber,
    language: item.json.Language || null,
    interest: item.json.Interest || null,
    interest_remarks: item.json['interest remarks'] || null, // Corrected for property with space
    last_contact: formatTimestamp(item.json.LastContact),
    last_contact_from_customer: formatTimestamp(item.json.LastContactFromCustomers),
    last_contact_from_company: formatTimestamp(item.json.LastContactedFromCompany),
    last_contact_from_user: formatTimestamp(item.json.LastContactedFromUser),
    created_at: formatTimestamp(item.json.CreatedAt),
    updated_at: formatTimestamp(item.json.UpdatedAt),
    last_channel: item.json.LastChannel || null,
    contact_owner: excludedOwners.has(contactOwnerName) ? null : contactOwnerName,
    contact_owner_email: item.json.ContactOwnerEmail || null,
    source: source,
    sremarks: sremarks,
    medium: medium,
    mremarks: mremarks,
    click_id: item.json.AdClickID || null,
    ad_source_url: item.json.AdSourceURL || null,
    ad_source_id: adSourceId,
    name: capitalizeText(item.json.FirstName || 'unknown'),
    branch: mapBranch(sremarks),
    conversationId: item.json.conversationId || null,
    sremarks_id: sremarks_id,
  };
});

// Return the result to the next node
return result;
chat.js
// Function to format the timestamp to 'YYYY-MM-DD HH:MM:SS'
function formatTimestamp(timestamp) {
  if (!timestamp) return null; // Return null if missing
  const date = new Date(timestamp);
  if (isNaN(date.getTime())) return null; // Return null for invalid date

  // Extract the year, month, day, hours, minutes, and seconds
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0'); // Month is 0-based
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

// Function to map lastChannelIdentityId to specific labels
function mapChannelIdentity(lastChannelIdentityId) {
  if (!lastChannelIdentityId) return null;

  if (lastChannelIdentityId.includes("409534172246677")) {
    return "fb_kyzn_id";
  } else if (lastChannelIdentityId.includes("17841468769957389")) {
    return "ig_kyzn_id";
  } else if (lastChannelIdentityId.includes("19190")) {
    return "fb_kuningan";
  } else if (lastChannelIdentityId.includes("17841453892878958")) {
    return "ig_kuningan";
  } else if (lastChannelIdentityId.includes("19191")) {
    return "fb_bsd";
  } else if (lastChannelIdentityId.includes("17841450110322840")) {
    return "ig_bsd";
  } else if (lastChannelIdentityId.includes("113207553436200")) {
    return "ig_kyzn_life";
  } else if (lastChannelIdentityId.includes("110429021829147")) {
    return "ig_kyzn_preschool";
  } else if (lastChannelIdentityId.includes("6285174420088")) {
    return "whatsapp";
  } else {
    return "whatsapp";
  }
}

// Function to map mremarks based on the value of sremarks
function mapMremarks(sremarks) {
  if (["fb_kyzn_id", "ig_kyzn_id", "fb_kuningan", "ig_kuningan", "fb_bsd", "ig_bsd"].includes(sremarks)) {
    return "dm";
  } else {
    return "wa"; // Default or fallback value
  }
}

// Function to map branch based on mremarks value
function mapBranch(sremarks) {
  const branchMapping = {
    fb_bsd: "KYZN BSD",
    ig_bsd: "KYZN BSD",
    fb_kuningan: "KYZN Kuningan",
    ig_kuningan: "KYZN Kuningan"
  };
  return branchMapping[sremarks] || "KYZN"; // Default branch value
}

// Function to convert text to Capitalized Case
function capitalizeText(text) {
  if (!text) return null; // Handle missing text
  return text
    .toLowerCase()
    .split(" ")
    .map(word => word.charAt(0).toUpperCase() + word.slice(1))
    .join(" ");
}

// List of names to check for exclusion in contact_owner
const excludedOwners = new Set([
  "KYZN", "Diadre Marketing", "Sales BSD", "Sales KNG", 
  "Lutfi CA", "FO BSD", "FO Kuningan", "Siska Permata", "Admin KYZN"
]);

// Get the input from the previous node
const data = items;

// Transform the data to the desired format with safe checks for undefined fields
const result = data.map(item => {
  const sremarks = mapChannelIdentity(item.json.lastChannelIdentityId);
  const mremarks = mapMremarks(sremarks);
  const rawContactOwner = item.json.assignee?.userInfo?.displayName || item.json.assignedTeam?.teamName || null;
  const contactOwner = excludedOwners.has(rawContactOwner) ? null : rawContactOwner;

  return {
    id: item.json.userProfile?.id || null,
    conversationId: item.json.conversationId || null,
    name: capitalizeText(item.json.userProfile?.firstName || null), // Convert to Capitalized Case
    phone: item.json.userProfile?.whatsAppAccount?.phone_number || null,
    created_at: formatTimestamp(item.json.userProfile?.createdAt),
    updated_at: formatTimestamp(item.json.userProfile?.updatedAt),
    last_contact_from_customer: formatTimestamp(item.json.userProfile?.lastContactFromCustomers),
    contact_owner: contactOwner, // Apply exclusion rule
    contact_owner_email: item.json.assignee?.userInfo?.email || null,
    last_channel: item.json.lastMessageChannel || 'whatsapp',
    sremarks_id: item.json.lastChannelIdentityId || null,
    sremarks: sremarks || 'whatsapp',
    mremarks: mremarks || 'wa',
    branch: mapBranch(sremarks) // Map branch based on sremarks
  };
});

// Return the result to the next node
return result;

Last updated