Автоматизируйте свою личную CRM с помощью Notion и Hazel Base

Введение

Hazelbase и Notion — это два мощных инструмента, которые можно использовать вместе для создания собственной CRM-системы. С помощью Hazelbase вы можете организовать данные из Интернета в сеть идентификации с миллиардами записей, которые каждый может использовать и вносить свой вклад. С Notion вы можете создать собственное приложение, которое можно использовать в качестве инструмента CRM. В этом сообщении блога мы рассмотрим, как создать приложение Node JS, а также решения для развертывания и будущие идеи для этого проекта.

Демонстрация приложения

Демо

Как это развивать

Предпосылки

  • Базовый JavaScript
  • Узел JS
  • Учетная запись понятия
  • Аккаунт Hazelbase

Создание базовой учетной записи Hazel

Для начала посетите и создайте свою учетную запись Hazelbase. После того, как вы зарегистрировали свою учетную запись, перейдите на Организации tab и создайте собственную организацию. Как только ваша организация будет создана, вы сможете получить доступ к панели инструментов. Чтобы помочь вам начать работу, мы предоставили пошаговое руководство на изображении ниже. Просто следуйте этим простым инструкциям, и вы будете готовы к работе в кратчайшие сроки.

Создание дашборда

Получение базового API-ключа Hazel

После того, как вы перешли на панель инструментов, вы можете выполнить следующие простые шаги, чтобы создать свой собственный личный ключ API:

  • Нажмите кнопку «Показать портал разработчика», расположенную на левой боковой панели страницы.
  • Дайте ключу API описательное имя, чтобы вы могли запомнить его назначение.
  • Нажмите кнопку «Создать», чтобы сгенерировать код.
  • Ваш API-ключ готов к использованию!
  • Чтобы лучше понять, как использовать ваш новый ключ, вы можете изучить GraphQL Explorer, который действует как своего рода игровая площадка, позволяя вам экспериментировать с различными запросами и мутациями.

Создание ключа API

Создание интеграции Notion

Команда Notion проделала поистине замечательную работу над документацией по разработке интеграций Notion. Этот пошаговый процесс можно найти здесь, и это невероятно полезное руководство для разработчиков, желающих создать интеграцию. В нем представлен обзор всего процесса и изложены требования для создания интеграции, а также даны полезные советы и рекомендации. Кроме того, есть подробные инструкции о том, как подключиться к Notion API и настроить необходимую аутентификацию. Благодаря обширной документации команды Notion у разработчиков не должно возникнуть проблем с созданием интеграции.

Для следующего раздела нам понадобится токен внутренней интеграции.

Добавление интеграции в созданную базу данных Notion

Теперь, когда у нас есть наша база данных, нам нужно предоставить доступ к интеграции Notion, которую мы создали на первом шаге.

Шаги можно увидеть в GIF ниже:

https://p-843661.f1.n0.cdn.getcloudapp.com/items/OAunvy8W/71524d66-99cc-41e7-bc1b-620ca32e1f2f.gif?v=aaf5b5a9b4705eeb13036d85af2f3b9c

Вы можете добавить в таблицу много разных полей, в зависимости от ваших потребностей. Для этого примера мы добавим:

  • Имя
  • Твиттер
  • LinkedIn
  • Электронная почта
  • Разное

Строки таблицы будут выглядеть примерно так:

https://i.imgur.com/o6ZC8t4.png

Создание приложения Node JS

Выполните следующие команды, чтобы создать проект и установить необходимые зависимости и зависимости для разработчиков:

mkdir notion-crm-hazelbase # Create new directory
cd notion-crm-hazelbase # Move to the created directory

npm init -y # Initialize the basic npm app

npm install @notionhq/client dotenv # Install the required dependencies
npm install --save-dev nodemon # Install the required dev dependencies

Редактирование package.json Файл

Изменить package.json файл, добавив следующую строку:

"type": "module",

Это гарантирует, что мы сможем использовать импорт ES6.

в scripts раздел, добавьте следующий скрипт:

"dev": "nodemon index.js"

Это будет прослушивать изменения и постоянно запускать приложение.

После его завершения, package.json файл выглядит примерно так.

{
  "name": "notion-crm-hazelbase",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon index.js"
  },
  "keywords": [],
  "author": "Rohith Gilla",
  "license": "ISC",
  "dependencies": {
    "@notionhq/client": "^0.3.2",
    "dotenv": "^10.0.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.12"
  }
}

Файл среды

Нам понадобится NOTION_DATABASE_ID, NOTION_SECRET_KEYи HAZEL_BASE_KEY чтобы завершить настройку интеграции Notion. Мы видели, как получить идентификатор базы данных и секретный ключ на первом этапе процесса интеграции. HAZEL_BASE_KEY было получено на начальных этапах.

Рекомендуется сохранить эти учетные данные в файле среды для удобства и облегчения доступа. я предоставил .env.example файл в репозитории GitHub, ссылка на который находится под сообщением в блоге. Этот файл должен дать представление о том, как должен выглядеть ваш файл среды, однако вам нужно будет заполнить детали вместо строк с правильной информацией.

NOTION_DATABASE_ID=""
NOTION_SECRET_KEY=""
HAZEL_BASE_KEY=""

Основной

Поскольку мы используем его как модуль для использования require ключевое слово, которое нам нужно определить, require следующим образом.

import { createRequire } from "module";
const require = createRequire(import.meta.url);

База Hazel раскрывает graphql конечная точка, которую можно использовать с помощью любого из популярных клиентов, таких как Apollo, Relay или даже библиотеки GraphQL.js. Для простоты воспользуемся POST метод для получения результатов вызова API. Этот метод удобен для отправки данных в конечную точку и получения обратно результатов, которые можно использовать для построения запроса и получения нужных данных. Кроме того, его легко понять, и его можно использовать с минимальной настройкой и настройкой.

const GRAPHQL_ENDPOINT = "

const searchQuery = () => `
query SearchV2($email: String) {
  searchV2(email: $email) {
    name {
      first
      last
      full
    }
    addresses {
      city
    }
    phoneAccounts {
      uri
      name
      carrier
      type
    }
    emailAddresses
    profiles {
      network
      url
    }
  }
}
`

Этот запрос был взят из API Explorer

Проводник API

Теперь мы отправим запрос GraphQL на конечную точку, используя адрес электронной почты пользователя, которого мы пытаемся найти. Этот запрос потенциально может предоставить нам соответствующую информацию, связанную с пользователем, такую ​​как его имя и фамилия, контактные данные и другую личную информацию. Кроме того, запрос также может предоставить нам любую дополнительную информацию, которая могла быть связана с пользователем, например его возраст, пол или любые другие предпочтения, которые они могли сохранить. Используя этот запрос, мы можем быстро и легко получить доступ к информации, необходимой для точной идентификации рассматриваемого пользователя.

const getSearchResults = async (email) => {
    try {
        const response = await fetch(GRAPHQL_ENDPOINT, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Authorization": `ApiKey ${process.env.HAZEL_BASE_KEY}`
            },
            body: JSON.stringify({
                query: searchQuery(),
                variables: {email},
            }),
        });
        const {data} = await response.json();

        return data.searchV2;
    } catch (e) {
        return [];
    }
}

Концепция инициализации API

import { Client } from "@notionhq/client";

const NOTION_SECRET_KEY = process.env.NOTION_SECRET_KEY;
const NOTION_DATABASE_ID = process.env.NOTION_DATABASE_ID;

const notion = new Client({ auth: NOTION_SECRET_KEY });

Запрос

Теперь нам нужно запросить таблицу Notion, которую мы создали на шаге 1.

const response = await notion.databases.query({
      database_id: NOTION_DATABASE_ID,
  });

Мы можем напрямую запросить базу данных с помощью database_id параметр. Мы также можем передать несколько параметров в filter, sortи установите размеры страниц. В этом примере мы не будем усложнять и будем передавать только database_id.

Нам нужно получить объекты столбца и, что более важно, текст в поле электронной почты.

Получить обязательные поля

Теперь нам нужны все объекты столбцов, а также, что более важно, текст в поле электронной почты.

const email = result.properties["Email"];
const name = result.properties["Name"];
const emailText = email[email.type][0]["plain_text"];
const isAdded = result.properties["Added"];
const isAddedBool = isAdded[isAdded.type];
const linkedIn = result.properties["LinkedIn"];
const misc = result.properties["Misc"];
const twitter = result.properties["Twitter"];

Переменные email, name, isAdded, linkedIn, twitterи misc содержать значения соответствующих полей. Это немного сумасшедшие вложенные объекты!

Чтобы получить текст письма, мы можем использовать следующую операцию: const emailText = email[email.type][0]["plain_text"];.

Кроме того, в базе данных есть поле, называемое Added, который является флажком. Это поможет нам понять, была ли строка уже обработана. Чтобы получить значение этого поля, мы можем использовать ту же операцию, что и для получения значений других полей.

const isAdded = result.properties["Added"];

Инициализировать переменные данными

var fullName = "Not Found";
var linkedInUrl = "Not Found";
var twitterUrl = "Not Found";
var miscData = "Not Found";

Мы хотим узнать следующие данные о человеке в нашем случае использования. Мы предварительно заполним их значением «Не найдено» и заменим фактическим значением, как только найдем его.

Поиск и сохранение

if (!isAddedBool) {
  
}

Во-первых, мы проверяем, является ли значение флажка trueчто указывает на то, что строка уже обработана.

Самая простая часть всего кода — попасть в конечную точку и получить результаты.

const searchResponse = await getSearchResults(emailText)

Получаем необходимые поля из ответа и сохраняем их в созданных нами ранее переменных.

if (searchResponse.length !== 0) {
    fullName = searchResponse[0].name.full;
    const linkedInObj = searchResponse[0].profiles.find(
      (profile) => profile.network === "linkedin"
    );
    const twitterObj = searchResponse[0].profiles.find(
      (profile) => profile.network === "twitter"
    );
    if (linkedInObj) {
      linkedInUrl = linkedInObj.url;
    }
    if (twitterObj) {
      twitterUrl = twitterObj.url;
    }
  }

Обновление API-интерфейса Notion

То, как работает обновление Notion API, не документировано должным образом для всех случаев использования, в документах API говорится только об обновлении логического или числового значения. Они не говорят об обновлении текста или других полей.

Немного покопавшись, я нашел, как обновить его, обратите внимание, что это может измениться в будущих версиях, но в основном это будет похоже.

Нам нужно построить объект для обновления полей, что можно сделать следующим образом.

var changedResult = {
    ...result.properties,
    Twitter: {
      ...twitter,
      rich_text: [
        {
          type: "text",
          text: {
            content: twitterUrl,
            link: twitterUrl !== "Not Found" ? { url: twitterUrl } : null,
          },
          plain_text: twitterUrl,
          href: null,
        },
      ],
    },
    LinkedIn: {
      ...linkedIn,
      rich_text: [
        {
          type: "text",
          text: {
            content: linkedInUrl,
            link:
              linkedInUrl !== "Not Found" ? { url: linkedInUrl } : null,
          },
          plain_text: linkedInUrl,
          href: null,
        },
      ],
    },
    Misc: {
      ...misc,
      rich_text: [
        {
          type: "text",
          text: { content: miscData, link: null },
          plain_text: miscData,
          href: null,
        },
      ],
    },
    Added: {
      ...isAdded,
      checkbox: true,
    },
    Name: {
      ...name,
      title: [
        {
          type: "text",
          text: { content: fullName, link: null },
          plain_text: fullName,
          href: null,
        },
      ],
    },
  };

Пройдемся по объекту и проверим, что происходит

LinkedIn: {
    ...linkedIn,
    rich_text: [
      {
        type: "text",
        text: {
          content: linkedInUrl,
          link:
            linkedInUrl !== "Not Found" ? { url: linkedInUrl } : null,
        },
        plain_text: linkedInUrl,
        href: null,
      },
    ],
  },

  • ...linkedIn мы распространяем начальные значения, так как они содержат несколько полей, таких как id и другие.
  • Нам нужно переопределить rich_text поле, для этого мы делаем следующее, добавляя следующий объект к этому rich_text множество.
{
    type: "text", 
    text: {
      content: linkedInUrl,
      link:
        linkedInUrl !== "Not Found" ? { url: linkedInUrl } : null,
    },
    plain_text: linkedInUrl,
    href: null,
  },

Аналогично поступаем с остальными полями.

Последний шаг обновите объект с помощью Notion API

Это довольно просто: мы берем обновленный объект и обновляем базу данных, используя понятие API.

await notion.pages.update({
  page_id: result.id,
  properties: changedResult,
});

Обработка ошибок

Мы будем держать его простым; вся функция будет завернута в try/catch блок, чтобы гарантировать, что любые ошибки, возникающие во время выполнения функции, могут быть обнаружены и обработаны соответствующим образом. Это поможет нам сохранить целостность нашей программы, так как любые возникающие ошибки не могут привести к ее сбою.

Запускать периодически

Функция, которую мы имеем, должна запускаться периодически, скажем, каждые 5 секунд, подобно заданию cron, но не заданию cron. Этого можно добиться, настроив таймер, который запускает функцию каждые 5 секунд, таким образом гарантируя, что функция всегда будет выполняться каждые 5 секунд.

Мы можем использовать JavaScript setTimeout функцию для достижения этого. setTimeout функция, которая принимает два аргумента; первый аргумент — это функция, которую нужно выполнить, а второй аргумент — это время в миллисекундах, по истечении которого функция должна быть выполнена. Поэтому мы можем использовать setTimeout настроить таймер, который будет запускать нашу функцию каждые 5 секунд (5000 миллисекунд).

setTimeout(main, 5000);

Объединение всего вместе

После того, как мы сделали все вышеперечисленные шаги, конечные результаты будут похожи на этот index.js файл

Репозиторий GitHub

Вы можете найти репозиторий здесь.

Пожалуйста, отметьте репозиторий, если он вам понравился.

Решения для развертывания

Здесь мы не будем рассматривать развертывание в этом сообщении блога, но мы предложим несколько бесплатных альтернатив. Вы можете развернуть приложения Node.js на Deta с помощью Deta Micros; узнать больше здесь. Deta Micros — отличное решение для тех, кто ищет простой в использовании и простой способ развертывания своих приложений Node.js. Vercel также предлагает Node.js Время выполнения как вариант для развертывания, предлагая интуитивно понятную и удобную платформу. Кроме того, вы можете ознакомиться StackBlitz и Повторить, оба из которых предоставляют удобные и простые решения для развертывания Node.js. Неважно, каковы ваши потребности, всегда найдется подходящее решение; это лишь некоторые из многих доступных вариантов.

Продолжайте доставлять и творите чудеса!!

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *