自分のCRMをNotionとHazel Baseで自動化する

はじめに

HazelbaseとNotionは、カスタムCRMシステムを作成するために一緒に使うことができる二つの強力なツールです。Hazelbaseでは、何十億もの記録があるアイデンティティネットワークにインターネットからデータを整理することができ、誰でも使ったり貢献することができます。Notionを使えば、CRMツールとして使えるカスタムアプリケーションを作成することができます。このブログ投稿では、Node JSアプリケーションの作成方法、デプロイソリューション、そしてこのプロジェクトのための今後のアイディアについて詳しく説明します。

アプリケーションデモ

デモ
デモへのリンク(画像)

開発方法

事前準備

  • 基本的なJavaScriptの知識
  • Node JS
  • Notionアカウント
  • Hazelbaseアカウント

Hazelbaseアカウントの作成

始めるには、https://dashboard.hazelbase.com/sign-inを訪れてHazelbaseアカウントを作成してください。アカウントを登録したら、Organisationsタブに進んで自分の組織を作成します。組織が作成されたら、ダッシュボードにアクセスすることができます。始めるのに役立つように、下の画像の手順のガイドを提供しています。これらの簡単な指示に従うだけで、あっという間に全部が整います。

ダッシュボード作成(画像)

Hazelbase APIキーの取得

ダッシュボードに移動したら、次の簡単な手順で個人用のAPIキーを作成することができます:

  • ページの左サイドバーにある「Show Developer Portal」ボタンをクリックします。
  • 目的を覚えておけるようにAPIキーに記述性のある名前を付けます。
  • 「Create」ボタンをクリックしてコードを生成します。
  • これでAPIキーが使えるようになります!
  • この新しいキーを使って何ができるのかより良く理解するため、さまざまなクエリーやミューテーションを実験できるような遊び場であるGraphQL Explorerを探検することができます。

APIキーの作成(画像)

Notion統合の作成

Notionチームは、Notion統合を開発するためのドキュメントに本当に注目すべき仕事をしています。このステップバイステッププロセスはこちらで見つけることができ、統合を作成したい開発者にとって大変便利なガイドです。プロセス全体の概要と統合を作成するための要件、有益なコツやガイダンスの提供、そしてNotionのAPIに接続して必要な認証を設定するための詳細な手順が説明されています。Notionチームの包括的なドキュメントを利用すれば、開発者は統合を作成する際に困ることはないでしょう。

次のセクションで使用する内部統合トークンが必要になります。

作成したNotionデータベースへの統合の追加

これでデータベースができたので、最初のステップで作成したNotion統合へのアクセス権を与える必要があります。

手順は以下のGIFで確認できます:

アクセス権の付与(GIF画像)

あなたのニーズに応じて、テーブルに多くの異なるフィールドを追加することができます。この例では、以下のフィールドを追加します:

  • 名前
  • Twitter
  • LinkedIn
  • メール
  • その他

テーブルの行は次のようになります:

テーブル行の様子(画像)

Node JSアプリケーションの作成

次のコマンドを実行して、プロジェクトを作成して必要な依存関係と開発依存関係をインストールします:

mkdir notion-crm-hazelbase # 新しいディレクトリを作成します
cd notion-crm-hazelbase # 作成したディレクトリに移動します

npm init -y # npmアプリの基本を初期化します

npm install @notionhq/client dotenv # 必要な依存関係をインストールします
npm install --save-dev nodemon # 必要な開発依存関係をインストールします

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統合セットアップを完了するには、NOTION_DATABASE_IDNOTION_SECRET_KEY、そしてHAZEL_BASE_KEYが必要になります。データベースIDとシークレットキーは統合プロセスの最初の手順で取得する方法を見ました。HAZEL_BASE_KEYは最初の手順で取得しました。

これらの資格情報を便宜とアクセスしやすいように環境ファイルに保存することをお勧めします。GitHubリポジトリには.env.exampleファイルを提供していますが、このファイルは環境ファイルがどのように見えるべきかのアイディアを提供します。しかし、正しい情報をストリングの代わりに詳細を入力する必要があります。

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

コア

requireキーワードを使用するために、次の方法でrequireを定義する必要があります。

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

Hazelbaseは、Apollo、Relay、またはGraphQL.jsライブラリといった人気のクライアントを使用して利用できるgraphqlエンドポイントを公開しています。簡単にするために、エンドポイントへのAPI呼び出し結果を取得するためのPOSTメソッドを使用しましょう。このメソッドは、データをエンドポイントに送信して結果を受け取り、クエリを構築して必要なデータを受け取るのに便利です。また、最小限のセットアップと設定で理解しやすく使用することができます。

const GRAPHQL_ENDPOINT = "https://api.hazelbase.com/graphql"

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 Explorer(画像)

では、探している利用者のメールアドレスを使用してエンドポイントに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 [];
    }
}

Notion 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 });

クエリング

もうすでに第1ステップで構築したNotionのテーブルをクエリしなければなりません。

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

database_idパラメーターを使って直接データベースをクエリできます。また、filtersortするための複数のパラメーターや、ページサイズを設定するためのパラメーターも渡すことが可能です。しかし、この例では単純にして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"];

emailnameisAddedlinkedIntwitter、そしてmiscの変数にはそれぞれのフィールドの値が入っています。少し複雑な入れ子になったオブジェクトです!

データ初期化

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

ケースにおいて私たちは個人に対する以下のデータを見つけ出します。最初に"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;
   <br><br>こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。<br>[https://dev.to/gillarohith/automate-your-personal-crm-with-notion-and-hazel-base-2j5](https://dev.to/gillarohith/automate-your-personal-crm-with-notion-and-hazel-base-2j5)