2024年にやったワークフロー自動化の振り返り〜クリスマスツリーを添えて🎅🎄〜

kadop
·

この記事はGoodpatchのアドベントカレンダーの6日目の記事です。

詳しい自己紹介は省きますが、2024年の前半はDesignOpsチームで組織開発や人材開発を行ってきましたが、2024年9月からは社長室で新規事業開発と少し役割が変わった年でもあります。

DesignOpsチームでは、Operetionsという言葉にもあるように業務改善や効率化に向き合うことも多く、繰り返し行うような業務を自動化をいくつかのツールを駆使してやってきました。今回のアドベントカレンダーでは今年やったワークフローの自動化について振り返ってみようと思います。といってもデザインに関わるものは、ほぼなくちょっとしたタスクの自動化という感じです🙏

こんなのこともできるのかと、少しでも業務効率化のきっかけにつながれば嬉しいです。

本題に入る前に☝️

自動化を行うにあたり特に好きなものがGoogle Apps Script(GAS)です。開発スキルが別に高いわけではないので、ChatGPTが出る前はできることが限られていたのですが、ChatGPTが出てからはスクリプトをChatGPTに出力してもらいさまざまなスクリプトでスプレッドシートの処理を中心に自動化していきました。

ぜひ、まだ触ったことないよ!という方にも触ってみていただいたいのでこの記事の後半で簡単なGAS導入もご紹介できればと思いますのでご参考に🎄

そのほか、主に自動化で使ったツールたちのご紹介

2024年にやったワークフローの自動化たち

ざっとやったものを上げてみました。それぞれ簡単に詳細をご紹介していきます。

  1. ダッシュボード化用のスプレッドシート整形

  2. 受注失注のSlackチャンネルへの通知

  3. Facebook広告の運用結果の吐き出し

  4. Xのポスト収集

  5. Google Search Consoleの結果の書き出しと考察

  6. 提案書格納DBをNotionで構築+Slackへの通知

  7. その他Difyで作成したボット

1. ダッシュボード化用のスプレッドシート整形

Goodpatchでは、全社の売上や商談、受注状況をLooker Studioを使いダッシュボード化しています。ダッシュボードのものになる数値データはSalesforceやスプレッドシートで管理しているものが多く、それらの数値データをダッシュボード用のスプレッドシートに集約し、データをLooker Studio用に整形しています。(本当は、BigQueryとかで集約できればいいのですが・・・)

Salesforceのデータはスプレッドシートのアドオンを使い、4時間毎にスプレッドシートに吐き出す用にしています。自動的に吐き出されたものを一部文字列に置き換えを行うためにGASを活用しています。

ワークフローの流れとしては下記になります。

Saleforceダッシュボードワークフロー

2. 受注失注のSlackチャンネルへの通知

リードや商談情報などはSalesforceで管理をしていますが、アカウントを持っているメンバーしか見れないこともあり、どんな案件が受注できたのか、失注してしまったのかなどの通知をSalesforceの商談ステータスが変わったらSlackに流す用にしています。

これは、ZapierというツールでSalesforceと連携し、特定の商談ステータスになったことをトリガーとしてSlackに通知をするようにしています。

受失注ステータスの変更だけでなく、それぞれの理由もSalesforceから引っ張ってきて全社メンバーが見れる状態にしています。営業メンバーがSalesforceの情報を入力することは業務上負荷も高いですが、より多くの人に情報を届けるような状態を作ることで、記録し溜めていくだけでなくみんなに知ってもらうという入力価値の向上にもつながっています。

受注通知ワークフロー

3. Facebook広告の運用結果の吐き出し

Facebook広告の結果は、Facebook広告上でみれますが割と見づらく、スプレッドシートへの自動書き出し機能もないです。一部スプレッドシートのアドオンで取得することもできますが、無料の範囲だと制限もあり運用結果を見るだけの課金ハードルも高いので、GASを使ってFacebook広告のAPIから広告結果を取得しスプレッドシートに定期的に書き出し、書き出した結果をLooker Studioでダッシュボード化するようにしています。

一見、APIを使ったりと複雑な気もしますが、ChatGPTが詳しく手順を教えてくれますし、GASのスクリプトもすべて書いてくれます。エンジニアリング知識が少なくとも対話しながら構築することができました。

Facebook広告のダッシュボード化

4. Xのポスト収集

Twitter時代はAPIを割と自由に使えたこともありさまざまなツールでTweetを取得できていましたが、イーロン体制になってからAPIの利用費が上がり各ツールでの提供がストップしてしまいました。もともとはZapierでも取得できていましたが非対応となってしまい、今はIFTTTを利用しています。(月額費用はかかりますが・・・)

自社のソリューションに関わるワードを検索ワードとして、IFTTTでPostを取得、取得したPostをSlackの指定したチャンネルに自動投稿するようにしています。

XのPost収集

人気なキーワードは、ノイズも多かったり、リポストやアカウント名の記載でも拾ってしまうのでそこは除外設定をしています。若干IFTTT独自のルールがあるようで最終的にいくついた除外は下記になります。

例えば:UX designのPostを収集した場合

"UX design" lang:ja -is:retweet -is:reply @i -@i

  • lang:ja:日本語のみの言語指定

  • -is:retweet:リポスト除外

  • -is:reply:引用ポスト除外

  • @i -@i:アカウント名にキーワードを記載している人のPost除外

ただ、日々Postは流れていくので本当に時間があるときしか見なくなってしまっています・・・ということで収集したPostをデイリーで要約するようなGASも試してみました。

IFTTTで取得したPOSTをスプレッドシートに収集し、収集したPostをGASで日毎でOpenAIのAPIを使い要約してもらうというものです。ここは、引き続き効率的に情報をキャッチアップできる仕組みを試していければと思います。

5. Google Search Consoleの結果の書き出しと考察

今年の5月くらいからGoodpatch BlogのSEO強化のプロジェクトを進めています。日々の結果をLooker Studioでダッシュボード化しみれるようにしているのですが、変化を定期的にキャッチアップしたいなと思い週次でのレポートを自動化してみました。

Google Search Consoleの結果を定期的にスプレッドシートに書き出し、GASを使ってOpenAIのAPI経由で結果の要約、分析、考察を行ってもらいSlackのチャンネルに投稿するようにしています。

Google Search Consoleの結果をスプレッドシートに書き出すのはアドオンがなく、Google Search ConsoleのAPIから取得する必要があり少しハードルは高いのですが、これもChatGPTさまに聞きながら組んでみました。数字の結果も正しく要約してくれ4o以降の精度は本当にすごいです。

検索結果の通知

6. 提案書格納DBをNotionで構築+Slackへの通知

Goodpatchでは、クライアントワークの提案書などは基本Google Driveに格納し閲覧できるようになっています。ただ、どんなプロジェクトでどんな提案をしたのかなどの情報はDriveで管理するのは難しく、提案書をナレッジとして共有しづらい状態になっています。

10月から提案を主導しているプロデューサーと連携して、どんな提案書がDriveに格納れているかをNotionでDB化し管理する取り組みを進めてきました。Driveに格納したらNotionのDBに手動でリンクと各プロパティを入れるというのも良いですが、忙しい中で継続的に行うのはハードルが高いときもあります。継続性という部分でワークフローの自動化に取り組みました。

Driveに指定した名称ルール(クライアント名を入れる、プロジェクト名を入れるなど)で提案書を格納をZapierのトリガーとして、NotionDBに追加を行います。提案書の名称からクライアント名やプロジェクト名をZapierで分解取得し、Notionのプロパティに自動的に設定します。ただ、すべてのプロパティを埋めることはできないため一部の登録となります。

登録したらSlackの特定のチャンネルにポストしナレッジとして共有する仕組みを整えています。

また、定期的にプロパティ未入力の提案書に関してはリマインドする仕組みも追加しました。Notionのオートメーションや通知は細かい設定ができないためNotionのAPIを取得し、GASで定期に未入力のプロパティをリストアップしSlackに通知するようにしています。

提案書かkんリワークフロー

7. その他Difyで作成したボット

トライアルでDifyを使ってワークフローを組み、タスクの自動化を行ってみています。

  • Slackに投稿された記事の要約

個人個人のtimesに気になるnoteなどの記事や参考になる記事が日常的に投稿されるのですが、すぐに読めないことも多くとりあえずスタンプをつけておきます。スタンプを押した記事を収集しておく個人チャンネルを作成していたのですが、スタンプを押したことをトリガーとしてZapier経由でスプレッドシート、スプレッドシートに入力されたURLをDifyに渡し、Dify内でChatGPTで要約しSlackへ要約内容を通知するようにしています。

生jの要約
  • UXリサーチの補助

最近は、一人で新規事業開発を行っており日々顧客になる方にインタビューを行っていてリします。インタビューの要約や個票(ペルソナシート化)作りは一人でやると時間がかかってしまい事業開発のスピードが遅くなり、負荷も高いです。ChatGPTやOpenAIのPlaygroundでも良いですが、簡単にワークフローを組めボット化できるのでDifyでサポートツールを作っています。

まだまだ、複雑なワークフローは組めていないのでいろいろと勉強しながら試しています。

GASを試してみる👍️

今回ご紹介したワークフローの自動化では、Zapierなど有料のツールもありましたが、一番手軽に使えるのがGASだと思っています。もちろんエンジニア知識が必要になってはくるのですが、ChatGPTである程度スクリプトを出すことができるので一度GASの手順さえ踏んでおけば応用しやすくなります。

ということでまだ、GAS使ったこと無いよ!という方はぜひ試してみてください。クリスマスも近いし、アドベントカレンダー企画でもあるのでクリスマスツリーをGASを使って描いてみたいと思います🎅

・スプレッドシートでクリスマスツリーを描こう🎄🖌️

今回もChatGPTにスプレッドシートでのクリスマスツリーの描き方を聞いてみました。

【手順】

  1. スプレッドシートを開く

  2. スプレッドシートの「拡張機能」からApps Scriptを起動

    (このようなスクリプトを入れる画面が表示されます)

  3. スクリプトをコピペする

    function createPerfectChristmasTree() {

    const sheetName = "PerfectChristmasTree"; // シート名

    const treeHeight = 50; // ツリーの高さ

    const scale = 0.7; // 幅のスケーリングファクター(0 < scale <= 1)

    const originalWidth = 2 * treeHeight - 1; // 元の幅

    let width = Math.round(originalWidth * scale); // スケール後の幅

    // 幅を奇数に調整

    if (width % 2 === 0) {

    width += 1;

    }

    const starPattern = [

    [0, 0, 0, 1, 0, 0, 0],

    [0, 0, 1, 0, 1, 0, 0],

    [0, 1, 0, 1, 0, 1, 0],

    [1, 0, 1, 0, 1, 0, 1],

    [0, 1, 0, 1, 0, 1, 0],

    [0, 0, 1, 0, 1, 0, 0],

    [0, 0, 0, 1, 0, 0, 0]

    ];

    const starHeight = starPattern.length; // 星の高さ

    const trunkHeight = Math.floor(treeHeight / 10); // 幹の高さ

    const trunkWidth = Math.floor(treeHeight / 5); // 幹の幅

    const totalHeight = starHeight + treeHeight + trunkHeight; // 全体の高さ

    // シートを取得または作成

    const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

    let sheet = spreadsheet.getSheetByName(sheetName);

    if (!sheet) {

    sheet = spreadsheet.insertSheet(sheetName);

    } else {

    sheet.clear(); // 既存のデータをクリア

    }

    // 必要な行数があるか確認し、足りなければ追加

    const currentRows = sheet.getMaxRows();

    if (currentRows < totalHeight) {

    sheet.insertRows(currentRows + 1, totalHeight - currentRows);

    }

    // 星を描画

    drawStar(sheet, width, starPattern);

    // ツリーを描画

    for (let row = starHeight + 1; row <= starHeight + treeHeight; row++) {

    const treeRow = row - starHeight;

    // スケーリングファクターを用いて行ごとの幅を計算

    let rowWidth = Math.round((2 * treeRow - 1) * scale);

    if (rowWidth < 1) rowWidth = 1; // 最小幅を1に設定

    // 奇数に調整

    if (rowWidth % 2 === 0) {

    rowWidth += 1;

    }

    const startCol = Math.floor((width - rowWidth) / 2) + 1; // 1-based に修正

    for (let col = 0; col < rowWidth; col++) {

    const currentCol = startCol + col;

    const randomDecoration = Math.random();

    if (randomDecoration < 0.03) {

    sheet.getRange(row, currentCol).setBackground("#FF0000"); // 赤いオーナメント

    } else if (randomDecoration < 0.06) {

    sheet.getRange(row, currentCol).setBackground("#FFD700"); // 金色のオーナメント

    } else {

    sheet.getRange(row, currentCol).setBackground("#008000"); // 緑(ツリー本体)

    }

    }

    }

    // 幹を描画

    const trunkStartRow = starHeight + treeHeight + 1;

    const trunkStartCol = Math.floor((width - trunkWidth) / 2) + 1; // 1-based に修正

    for (let row = trunkStartRow; row < trunkStartRow + trunkHeight; row++) {

    for (let col = 0; col < trunkWidth; col++) {

    const currentCol = trunkStartCol + col;

    sheet.getRange(row, currentCol).setBackground("#8B4513"); // 茶色(幹の色)

    }

    }

    // 列幅と行高さを調整

    sheet.setColumnWidths(1, width, 15); // 列幅を調整

    sheet.setRowHeights(1, totalHeight, 15); // 行高さを調整

    }

    /**

    * 星を描画する関数

    * @param {Sheet} sheet - スプレッドシートのシートオブジェクト

    * @param {number} width - ツリーの幅

    * @param {Array} starPattern - 星のパターン配列

    */

    function drawStar(sheet, width, starPattern) {

    const starWidthPattern = starPattern[0].length;

    // 星の中央位置を計算

    const centerCol = Math.floor(width / 2) + 1;

    for (let i = 0; i < starPattern.length; i++) {

    const row = i + 1; // 星はシートの最上部から始まる

    const pattern = starPattern[i];

    const patternWidth = pattern.length;

    const startCol = centerCol - Math.floor(patternWidth / 2);

    for (let j = 0; j < patternWidth; j++) {

    const cellValue = pattern[j];

    if (cellValue === 1) {

    sheet.getRange(row, startCol + j).setBackground("#FFD700"); // 星の色(ゴールド)

    }

    }

    }

    }

  4. 「保存」してスクリプトを「実行」する

    (初回のみスクリプトを実行する際はGoogleアカウントの承認が必要になるため画面の指示に従い承認をしてください)

  5. スクリプトを実行するとスプレッドシートにクリスマスツリーが描かれます🎄

    (一度目の実行で右側の描画が崩れることがあるのでその場合はもう一度「実行」を押してみてください)

まとめ

スクリプトさえかければスプレッドシートなどの処理を簡単に行うことができるので、身近なルーティーな作業などでぜひワークフローの自動化を試してみてください。

また、Difyなどの手軽にAIを使えるツールもどんどん増えてきており、AIエージェントのサービスも更に増えてくると考えられます。なかなか新しいサービスの導入には足踏みしてしまう方もいるかも知れませんが、今まで時間がかかっていた単純作業をほんの数秒で終わらすこともできるのでぜひ試してみてください。

@kadop
Goodpatchというデザイン会社で新規事業開発を担当。 UXデザインやサービスデザインなどが専門