KYZN Docs
Home
  • Welcome
  • Intro
    • What is KYZN?
    • Age Group
  • KYZN Funnel
    • Glossary
      • General
      • Tracking Framework
    • Report
      • TAC Funnel
      • TCC Funnel
      • TAC Sleekflow
  • KYZN CRM
    • Glossary
      • My Leads
        • Add Leads
        • Add Family Leads
        • Add Appointment
        • Add Membership
        • Edit Branch
        • Edit PIC
        • Edit & Delete Leads
        • Search Leads
        • Reschedule Appointment
        • Clear Abnormal Stage
      • Approach
      • Pool
      • My Appt
        • Edit & Delete Appointment
        • Trial Form
      • My Convert
      • User Manager
      • UTM Generator
      • Assign PIC
      • Set Target
      • Schedule List
    • Event Bulk Data
  • Digital System
    • ETL Process
      • Query Checking
        • Cek Funnel Stage
        • Insert from temp_leads
        • Insert from sleekflow
        • Check Duplicate
        • Update Source Ads
        • Conversion Duration Analysist
        • Cek branch tidak match
        • Select Potential Contact
      • Query View
        • TAC Combined
        • TAC
        • TAC Appt
        • TAC Appt - Appt
        • TAC Appt - MQL
        • TAC Appt - MQLplus
        • TAC Appt - Tourplus
        • TAC Appt - Trialplus
        • TAC Convert
        • TAC Inbound
        • TAC Leads
        • TAC MQL
        • TAC MQLplus
        • TAC Tourplus
        • TAC Trialplus
        • Target View
        • Leads View
        • Appt View
        • Actual vs Target
        • All Time Leads Stages
        • All Time Appt Date
        • Budget Control
      • Database Management
        • pgAdmin
        • Looker Studio
  • Changelog
    • 2025-03
Powered by GitBook
On this page
  • Push Sleekflow Inbound to TAC Sleekflow
  • Analytics
  • Key Points :
  • HTTP Request
  • Code
  1. KYZN Funnel
  2. Report

TAC Sleekflow

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

PreviousTCC FunnelNextGlossary

Last updated 4 months ago

Push Sleekflow Inbound to TAC Sleekflow

Setiap 3 jam, semua data contact akan di transfer ke database TAC Sleekflow.

Analytics

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

Method

GET

URL

URL

URL

Send Headers

ON

Header Parameters

X-Sleekflow-Api-Key

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;

https://api.sleekflow.io/api/contact?limit=100&offset=0
https://api.sleekflow.io/api/conversation/all?limit=100&offset=0&status=closed
https://api.sleekflow.io/api/conversation/all?limit=100&offset=0&status=open
TAC Sleekflow