diff --git a/.gitignore b/.gitignore index a47ba7c..8569c5b 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,25 @@ test_*.json # Backup files *.bak -*.backup \ No newline at end of file +*.backup + +# Workflow backup directories (created during renaming) +workflow_backups/ + +# Database files (SQLite) +*.db +*.sqlite +*.sqlite3 +workflows.db + +# Rename logs +workflow_rename_log.json + +# Node.js artifacts (if using npm) +node_modules/ +package-lock.json + +# Python package files +*.egg-info/ +dist/ +build/ \ No newline at end of file diff --git a/comprehensive_workflow_renamer.py b/comprehensive_workflow_renamer.py new file mode 100644 index 0000000..eda5f59 --- /dev/null +++ b/comprehensive_workflow_renamer.py @@ -0,0 +1,396 @@ +#!/usr/bin/env python3 +""" +Comprehensive N8N Workflow Renamer +Complete standardization of all 2053+ workflows with uniform naming convention. +""" + +import json +import os +import glob +import re +import shutil +from typing import Dict, List, Any, Optional, Tuple +from pathlib import Path + +class ComprehensiveWorkflowRenamer: + """Renames ALL workflows to uniform 0001-9999 standard with intelligent analysis.""" + + def __init__(self, workflows_dir: str = "workflows"): + self.workflows_dir = workflows_dir + self.rename_log = [] + self.errors = [] + self.backup_dir = "workflow_backups" + + def analyze_all_workflows(self) -> Dict[str, Any]: + """Analyze all workflow files and generate comprehensive rename plan.""" + if not os.path.exists(self.workflows_dir): + print(f"❌ Workflows directory '{self.workflows_dir}' not found.") + return {'workflows': [], 'total': 0, 'errors': []} + + json_files = glob.glob(os.path.join(self.workflows_dir, "*.json")) + + if not json_files: + print(f"❌ No JSON files found in '{self.workflows_dir}' directory.") + return {'workflows': [], 'total': 0, 'errors': []} + + print(f"πŸ” Analyzing {len(json_files)} workflow files...") + + workflows = [] + for file_path in json_files: + try: + workflow_data = self._analyze_workflow_file(file_path) + if workflow_data: + workflows.append(workflow_data) + except Exception as e: + error_msg = f"Error analyzing {file_path}: {str(e)}" + print(f"❌ {error_msg}") + self.errors.append(error_msg) + continue + + # Sort by current filename for consistent numbering + workflows.sort(key=lambda x: x['current_filename']) + + # Assign new sequential numbers + for i, workflow in enumerate(workflows, 1): + workflow['new_number'] = f"{i:04d}" + workflow['new_filename'] = self._generate_new_filename(workflow, i) + + return { + 'workflows': workflows, + 'total': len(workflows), + 'errors': self.errors + } + + def _analyze_workflow_file(self, file_path: str) -> Optional[Dict[str, Any]]: + """Analyze a single workflow file and extract metadata for renaming.""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + data = json.load(f) + except (json.JSONDecodeError, UnicodeDecodeError) as e: + print(f"❌ Error reading {file_path}: {str(e)}") + return None + + filename = os.path.basename(file_path) + + # Extract workflow metadata + workflow = { + 'current_filename': filename, + 'current_path': file_path, + 'name': data.get('name', filename.replace('.json', '')), + 'workflow_id': data.get('id', ''), + 'active': data.get('active', False), + 'nodes': data.get('nodes', []), + 'connections': data.get('connections', {}), + 'tags': data.get('tags', []), + 'created_at': data.get('createdAt', ''), + 'updated_at': data.get('updatedAt', '') + } + + # Analyze nodes for intelligent naming + node_count = len(workflow['nodes']) + workflow['node_count'] = node_count + + # Determine complexity + if node_count <= 5: + complexity = 'Simple' + elif node_count <= 15: + complexity = 'Standard' + else: + complexity = 'Complex' + workflow['complexity'] = complexity + + # Find services and trigger type + services, trigger_type = self._analyze_nodes(workflow['nodes']) + workflow['services'] = list(services) + workflow['trigger_type'] = trigger_type + + # Determine purpose from name and nodes + workflow['purpose'] = self._determine_purpose(workflow['name'], workflow['nodes']) + + return workflow + + def _analyze_nodes(self, nodes: List[Dict]) -> Tuple[set, str]: + """Analyze nodes to determine services and trigger type.""" + services = set() + trigger_type = 'Manual' + + for node in nodes: + node_type = node.get('type', '') + node_name = node.get('name', '') + + # Determine trigger type + if any(x in node_type.lower() for x in ['webhook', 'http']): + trigger_type = 'Webhook' + elif any(x in node_type.lower() for x in ['cron', 'schedule', 'interval']): + trigger_type = 'Scheduled' + elif 'trigger' in node_type.lower() and trigger_type == 'Manual': + trigger_type = 'Triggered' + + # Extract service names + if node_type.startswith('n8n-nodes-base.'): + service = node_type.replace('n8n-nodes-base.', '') + service = service.replace('Trigger', '').replace('trigger', '') + + # Clean up service names + service_mapping = { + 'webhook': 'Webhook', + 'httpRequest': 'HTTP', + 'cron': 'Cron', + 'gmail': 'Gmail', + 'slack': 'Slack', + 'googleSheets': 'GoogleSheets', + 'airtable': 'Airtable', + 'notion': 'Notion', + 'telegram': 'Telegram', + 'discord': 'Discord', + 'twitter': 'Twitter', + 'github': 'GitHub', + 'hubspot': 'HubSpot', + 'salesforce': 'Salesforce', + 'stripe': 'Stripe', + 'shopify': 'Shopify', + 'trello': 'Trello', + 'asana': 'Asana', + 'clickup': 'ClickUp', + 'calendly': 'Calendly', + 'zoom': 'Zoom', + 'mattermost': 'Mattermost', + 'microsoftTeams': 'Teams', + 'googleCalendar': 'GoogleCalendar', + 'googleDrive': 'GoogleDrive', + 'dropbox': 'Dropbox', + 'onedrive': 'OneDrive', + 'aws': 'AWS', + 'azure': 'Azure', + 'googleCloud': 'GCP' + } + + clean_service = service_mapping.get(service, service.title()) + + # Skip utility nodes + if clean_service not in ['Set', 'Function', 'If', 'Switch', 'Merge', 'StickyNote', 'NoOp']: + services.add(clean_service) + + return services, trigger_type + + def _determine_purpose(self, name: str, nodes: List[Dict]) -> str: + """Determine workflow purpose from name and node analysis.""" + name_lower = name.lower() + + # Purpose keywords mapping + purpose_keywords = { + 'create': ['create', 'add', 'new', 'generate', 'build'], + 'update': ['update', 'modify', 'change', 'edit', 'patch'], + 'sync': ['sync', 'synchronize', 'mirror', 'replicate'], + 'send': ['send', 'email', 'message', 'notify', 'alert'], + 'import': ['import', 'load', 'fetch', 'get', 'retrieve'], + 'export': ['export', 'save', 'backup', 'archive'], + 'monitor': ['monitor', 'check', 'watch', 'track', 'status'], + 'process': ['process', 'transform', 'convert', 'parse'], + 'automate': ['automate', 'workflow', 'bot', 'automation'] + } + + for purpose, keywords in purpose_keywords.items(): + if any(keyword in name_lower for keyword in keywords): + return purpose.title() + + # Default purpose based on node analysis + return 'Automation' + + def _generate_new_filename(self, workflow: Dict, number: int) -> str: + """Generate new standardized filename.""" + # Format: 0001_Service1_Service2_Purpose_Trigger.json + + services = workflow['services'][:2] # Max 2 services in filename + purpose = workflow['purpose'] + trigger = workflow['trigger_type'] + + # Build filename components + parts = [f"{number:04d}"] + + # Add services + if services: + parts.extend(services) + + # Add purpose + parts.append(purpose) + + # Add trigger if not Manual + if trigger != 'Manual': + parts.append(trigger) + + # Join and clean filename + filename = '_'.join(parts) + filename = re.sub(r'[^\w\-_]', '', filename) # Remove special chars + filename = re.sub(r'_+', '_', filename) # Collapse multiple underscores + filename = filename.strip('_') # Remove leading/trailing underscores + + return f"{filename}.json" + + def create_backup(self) -> bool: + """Create backup of current workflows directory.""" + try: + if os.path.exists(self.backup_dir): + shutil.rmtree(self.backup_dir) + + shutil.copytree(self.workflows_dir, self.backup_dir) + print(f"βœ… Backup created at: {self.backup_dir}") + return True + except Exception as e: + print(f"❌ Failed to create backup: {e}") + return False + + def execute_rename_plan(self, rename_plan: Dict[str, Any], dry_run: bool = True) -> bool: + """Execute the comprehensive rename plan.""" + if not rename_plan['workflows']: + print("❌ No workflows to rename.") + return False + + print(f"\n{'πŸ” DRY RUN - ' if dry_run else 'πŸš€ EXECUTING - '}Renaming {rename_plan['total']} workflows") + + if not dry_run: + if not self.create_backup(): + print("❌ Cannot proceed without backup.") + return False + + success_count = 0 + + for workflow in rename_plan['workflows']: + old_path = workflow['current_path'] + new_filename = workflow['new_filename'] + new_path = os.path.join(self.workflows_dir, new_filename) + + # Check for filename conflicts + if os.path.exists(new_path) and old_path != new_path: + print(f"⚠️ Conflict: {new_filename} already exists") + continue + + if dry_run: + print(f"πŸ“ {workflow['current_filename']} β†’ {new_filename}") + else: + try: + os.rename(old_path, new_path) + self.rename_log.append({ + 'old': workflow['current_filename'], + 'new': new_filename, + 'services': workflow['services'], + 'purpose': workflow['purpose'], + 'trigger': workflow['trigger_type'] + }) + success_count += 1 + print(f"βœ… {workflow['current_filename']} β†’ {new_filename}") + except Exception as e: + error_msg = f"❌ Failed to rename {workflow['current_filename']}: {e}" + print(error_msg) + self.errors.append(error_msg) + + if not dry_run: + print(f"\nπŸŽ‰ Rename complete: {success_count}/{rename_plan['total']} workflows renamed") + self._save_rename_log() + + return True + + def _save_rename_log(self): + """Save detailed rename log to file.""" + log_data = { + 'timestamp': os.popen('date').read().strip(), + 'total_renamed': len(self.rename_log), + 'errors': self.errors, + 'renames': self.rename_log + } + + with open('workflow_rename_log.json', 'w', encoding='utf-8') as f: + json.dump(log_data, f, indent=2, ensure_ascii=False) + + print(f"πŸ“„ Rename log saved to: workflow_rename_log.json") + + def generate_report(self, rename_plan: Dict[str, Any]) -> str: + """Generate comprehensive rename report.""" + workflows = rename_plan['workflows'] + total = rename_plan['total'] + + # Statistics + services_count = {} + purposes_count = {} + triggers_count = {} + + for workflow in workflows: + for service in workflow['services']: + services_count[service] = services_count.get(service, 0) + 1 + + purposes_count[workflow['purpose']] = purposes_count.get(workflow['purpose'], 0) + 1 + triggers_count[workflow['trigger_type']] = triggers_count.get(workflow['trigger_type'], 0) + 1 + + report = f""" +# 🎯 Comprehensive Workflow Rename Plan + +## πŸ“Š Overview +- **Total workflows**: {total} +- **Naming convention**: 0001-{total:04d}_Service1_Service2_Purpose_Trigger.json +- **Quality improvement**: 100% standardized naming + +## 🏷️ Service Distribution +""" + + for service, count in sorted(services_count.items(), key=lambda x: x[1], reverse=True)[:10]: + report += f"- **{service}**: {count} workflows\n" + + report += f"\n## 🎯 Purpose Distribution\n" + for purpose, count in sorted(purposes_count.items(), key=lambda x: x[1], reverse=True): + report += f"- **{purpose}**: {count} workflows\n" + + report += f"\n## ⚑ Trigger Distribution\n" + for trigger, count in sorted(triggers_count.items(), key=lambda x: x[1], reverse=True): + report += f"- **{trigger}**: {count} workflows\n" + + report += f""" +## πŸ“ Naming Examples +""" + + for i, workflow in enumerate(workflows[:10]): + report += f"- `{workflow['current_filename']}` β†’ `{workflow['new_filename']}`\n" + + if len(workflows) > 10: + report += f"... and {len(workflows) - 10} more workflows\n" + + return report + + +def main(): + """Main execution function.""" + import argparse + + parser = argparse.ArgumentParser(description='Comprehensive N8N Workflow Renamer') + parser.add_argument('--analyze', action='store_true', help='Analyze all workflows and create rename plan') + parser.add_argument('--execute', action='store_true', help='Execute the rename plan (requires --analyze first)') + parser.add_argument('--dry-run', action='store_true', help='Show rename plan without executing') + parser.add_argument('--report', action='store_true', help='Generate comprehensive report') + + args = parser.parse_args() + + renamer = ComprehensiveWorkflowRenamer() + + if args.analyze or args.dry_run or args.report: + print("πŸ” Analyzing all workflows...") + rename_plan = renamer.analyze_all_workflows() + + if args.report: + report = renamer.generate_report(rename_plan) + print(report) + + if args.dry_run: + renamer.execute_rename_plan(rename_plan, dry_run=True) + + if args.execute: + confirm = input(f"\n⚠️ This will rename {rename_plan['total']} workflows. Continue? (yes/no): ") + if confirm.lower() == 'yes': + renamer.execute_rename_plan(rename_plan, dry_run=False) + else: + print("❌ Rename cancelled.") + + else: + parser.print_help() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/static/index.html b/static/index.html index a251942..b2d1cbc 100644 --- a/static/index.html +++ b/static/index.html @@ -108,27 +108,24 @@ position: sticky; top: 0; z-index: 100; - backdrop-filter: blur(10px); } .search-section { display: flex; - gap: 1rem; align-items: center; - flex-wrap: wrap; + gap: 1rem; margin-bottom: 1rem; } .search-input { flex: 1; - min-width: 300px; padding: 0.75rem 1rem; - border: 2px solid var(--border); + border: 1px solid var(--border); border-radius: 0.5rem; - background: var(--bg-secondary); + background: var(--bg); color: var(--text); font-size: 1rem; - transition: all 0.2s ease; + min-width: 300px; } .search-input:focus { @@ -139,8 +136,8 @@ .filter-section { display: flex; - gap: 1rem; align-items: center; + gap: 1rem; flex-wrap: wrap; } @@ -154,37 +151,29 @@ font-size: 0.875rem; font-weight: 500; color: var(--text-secondary); - white-space: nowrap; } - select, input[type="checkbox"] { - padding: 0.5rem 0.75rem; + .filter-group select { + padding: 0.5rem; border: 1px solid var(--border); border-radius: 0.375rem; - background: var(--bg-secondary); + background: var(--bg); color: var(--text); font-size: 0.875rem; } .theme-toggle { - padding: 0.5rem 1rem; + background: var(--bg-tertiary); border: 1px solid var(--border); - border-radius: 0.375rem; - background: var(--bg-secondary); - color: var(--text); + border-radius: 0.5rem; + padding: 0.5rem 1rem; cursor: pointer; - transition: all 0.2s ease; + font-size: 1rem; margin-left: auto; } - .theme-toggle:hover { - background: var(--bg-tertiary); - } - .results-info { - display: flex; - justify-content: space-between; - align-items: center; + margin-top: 1rem; font-size: 0.875rem; color: var(--text-secondary); } @@ -192,7 +181,6 @@ /* Main Content */ .main { padding: 2rem 0; - min-height: 50vh; } /* States */ @@ -201,42 +189,31 @@ padding: 4rem 2rem; } + .state .icon { + font-size: 4rem; + margin-bottom: 1rem; + } + .state h3 { + font-size: 1.5rem; margin-bottom: 0.5rem; color: var(--text); } .state p { color: var(--text-secondary); - } - - .loading .icon { - font-size: 3rem; - margin-bottom: 1rem; - animation: pulse 2s infinite; - } - - @keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.5; } - } - - .error .icon { - font-size: 3rem; - margin-bottom: 1rem; - color: var(--error); + margin-bottom: 2rem; } .retry-btn { - margin-top: 1rem; - padding: 0.75rem 1.5rem; background: var(--primary); color: white; border: none; + padding: 0.75rem 1.5rem; border-radius: 0.5rem; cursor: pointer; + font-size: 1rem; font-weight: 500; - transition: all 0.2s ease; } .retry-btn:hover { @@ -246,7 +223,7 @@ /* Workflow Grid */ .workflow-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); gap: 1.5rem; } @@ -255,59 +232,46 @@ border: 1px solid var(--border); border-radius: 0.75rem; padding: 1.5rem; + box-shadow: var(--shadow); transition: all 0.2s ease; cursor: pointer; position: relative; } .workflow-card:hover { - border-color: var(--primary); box-shadow: var(--shadow-lg); + border-color: var(--primary); transform: translateY(-2px); } .workflow-header { display: flex; + align-items: center; justify-content: space-between; - align-items: flex-start; margin-bottom: 1rem; - gap: 1rem; } .workflow-meta { display: flex; align-items: center; - gap: 0.75rem; - flex-wrap: wrap; - flex: 1; + gap: 0.5rem; + font-size: 0.875rem; + color: var(--text-secondary); } .status-dot { - width: 0.75rem; - height: 0.75rem; + width: 8px; + height: 8px; border-radius: 50%; - flex-shrink: 0; } - .status-active { - background: var(--success); - animation: pulse-green 2s infinite; - } - - .status-inactive { - background: var(--text-muted); - } - - @keyframes pulse-green { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.6; } - } + .status-active { background: var(--success); } + .status-inactive { background: var(--text-muted); } .complexity-dot { - width: 0.5rem; - height: 0.5rem; + width: 8px; + height: 8px; border-radius: 50%; - flex-shrink: 0; } .complexity-low { background: var(--success); } @@ -317,85 +281,216 @@ .trigger-badge { background: var(--primary); color: white; - padding: 0.25rem 0.75rem; - border-radius: 1rem; + padding: 0.25rem 0.5rem; + border-radius: 0.375rem; font-size: 0.75rem; font-weight: 500; - text-transform: uppercase; - letter-spacing: 0.05em; - white-space: nowrap; } .workflow-title { - font-size: 1.125rem; + font-size: 1.25rem; font-weight: 600; margin-bottom: 0.5rem; color: var(--text); line-height: 1.4; - overflow-wrap: break-word; } .workflow-description { color: var(--text-secondary); - font-size: 0.875rem; - line-height: 1.5; margin-bottom: 1rem; - overflow-wrap: break-word; + line-height: 1.5; } .workflow-integrations { margin-top: 1rem; - padding-top: 1rem; - border-top: 1px solid var(--border); } .integrations-title { - font-size: 0.75rem; - font-weight: 600; + font-size: 0.875rem; + font-weight: 500; color: var(--text-secondary); margin-bottom: 0.5rem; - text-transform: uppercase; - letter-spacing: 0.05em; } .integrations-list { display: flex; flex-wrap: wrap; - gap: 0.5rem; + gap: 0.25rem; } .integration-tag { background: var(--bg-tertiary); - color: var(--text); - padding: 0.25rem 0.5rem; + color: var(--text-secondary); + padding: 0.125rem 0.5rem; border-radius: 0.25rem; font-size: 0.75rem; + border: 1px solid var(--border); + } + + .workflow-actions { + display: flex; + gap: 0.5rem; + margin-top: 1rem; + padding-top: 1rem; + border-top: 1px solid var(--border); + } + + .action-btn { + padding: 0.5rem 1rem; + border: 1px solid var(--border); + border-radius: 0.375rem; + background: var(--bg); + color: var(--text); + text-decoration: none; + font-size: 0.875rem; font-weight: 500; - } - - .load-more { - text-align: center; - padding: 2rem 0; - } - - .load-more-btn { - padding: 0.75rem 2rem; - background: var(--primary); - color: white; - border: none; - border-radius: 0.5rem; cursor: pointer; - font-weight: 500; transition: all 0.2s ease; } - .load-more-btn:hover:not(:disabled) { + .action-btn:hover { + background: var(--bg-tertiary); + border-color: var(--primary); + } + + .action-btn.primary { + background: var(--primary); + color: white; + border-color: var(--primary); + } + + .action-btn.primary:hover { background: var(--primary-dark); } - .load-more-btn:disabled { - opacity: 0.5; - cursor: not-allowed; + /* Load More */ + .load-more { + text-align: center; + margin-top: 2rem; + } + + .load-more-btn { + background: var(--primary); + color: white; + border: none; + padding: 0.75rem 2rem; + border-radius: 0.5rem; + cursor: pointer; + font-size: 1rem; + font-weight: 500; + } + + .load-more-btn:hover { + background: var(--primary-dark); + } + + /* Modal */ + .modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + padding: 1rem; + } + + .modal-content { + background: var(--bg); + border-radius: 0.75rem; + max-width: 800px; + width: 100%; + max-height: 90vh; + overflow-y: auto; + position: relative; + } + + .modal-header { + padding: 1.5rem; + border-bottom: 1px solid var(--border); + display: flex; + align-items: center; + justify-content: space-between; + } + + .modal-title { + font-size: 1.25rem; + font-weight: 600; + } + + .modal-close { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + padding: 0.25rem; + color: var(--text-secondary); + } + + .modal-body { + padding: 1.5rem; + } + + .workflow-detail { + margin-bottom: 1rem; + } + + .workflow-detail h4 { + font-size: 0.875rem; + font-weight: 600; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 0.5rem; + } + + .section-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.5rem; + } + + .copy-btn { + background: var(--primary); + color: white; + border: none; + padding: 0.25rem 0.5rem; + border-radius: 0.25rem; + font-size: 0.75rem; + cursor: pointer; + transition: all 0.2s ease; + display: flex; + align-items: center; + gap: 0.25rem; + } + + .copy-btn:hover { + background: var(--primary-dark); + } + + .copy-btn.copied { + background: var(--success); + } + + .copy-btn.copied:hover { + background: var(--success); + } + + .json-viewer { + background: var(--bg-secondary); + border: 1px solid var(--border); + border-radius: 0.5rem; + padding: 1rem; + font-family: 'Courier New', monospace; + font-size: 0.875rem; + overflow-x: auto; + max-height: 400px; + white-space: pre-wrap; } .hidden { @@ -552,10 +647,65 @@ + + + \n \n\n\n
\n

n8n Subworkflow Dependency Graph with Mermaid

\n
\n
\n
\n\n \n\n \n\n\n" - }, - "typeVersion": 1.1 - }, - { - "id": "d9b0e9be-1794-4f5e-899c-b5d1e22baa58", - "name": "Sticky Note11", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 680, - -320 - ], - "parameters": { - "color": 5, - "width": 653.2415806326139, - "height": 140.62930090784633, - "content": "## About this workflow\nThis workflow analyzes an n8n instance to detect dependencies between workflows. It identifies which workflows call others ([sub-workflows](https://docs.n8n.io/flow-logic/subworkflows/)), builds a dependency graph, and automatically tags subworkflows with their calling workflows. This makes it easier to track dependencies, optimize workflow structures, and maintain documentation in complex n8n environments." - }, - "typeVersion": 1 - }, - { - "id": "357037ff-f5f7-4b5d-9b72-7c2aec393de4", - "name": "Sticky Note12", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1360, - -320 - ], - "parameters": { - "color": 4, - "width": 266.5295926113459, - "height": 95.5709893724457, - "content": "## About the maker\n**[Find Ludwig Gerdes on LinkedIn](https://www.linkedin.com/in/ludwiggerdes)**" - }, - "typeVersion": 1 - } - ], - "active": true, - "pinData": {}, - "settings": { - "executionOrder": "v1" - }, - "versionId": "f1c5dcd4-bcdb-4336-922f-656adc9c36a6", - "connections": { - "Merge": { - "main": [ - [ - { - "node": "GET all tags again", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET all tags": { - "main": [ - [ - { - "node": "Remove existing tags from new_callers list", - "type": "main", - "index": 0 - } - ] - ] - }, - "Create new tags": { - "main": [ - [ - { - "node": "Return original pass through values", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET workflow(s)": { - "main": [ - [ - { - "node": "Exclude missing workflows", - "type": "main", - "index": 0 - } - ] - ] - }, - "And every Sunday": { - "main": [ - [ - { - "node": "GET all workflows", - "type": "main", - "index": 0 - } - ] - ] - }, - "SET instance_url": { - "main": [ - [ - { - "node": "GET all tags", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET all workflows": { - "main": [ - [ - { - "node": "List callers of subworkflows", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET all tags again": { - "main": [ - [ - { - "node": "Create tag id:name dictionary", - "type": "main", - "index": 0 - } - ] - ] - }, - "If any new callers": { - "main": [ - [ - { - "node": "Split out new callers as new tags", - "type": "main", - "index": 0 - } - ], - [ - { - "node": "Merge", - "type": "main", - "index": 1 - } - ] - ] - }, - "Update workflow tags": { - "main": [ - [ - { - "node": "Return dependency graph data", - "type": "main", - "index": 0 - } - ] - ] - }, - "Loop through workflows": { - "main": [ - [ - { - "node": "Combine dependency graph values into labels", - "type": "main", - "index": 0 - }, - { - "node": "Format workflow relationship data for rendering", - "type": "main", - "index": 0 - } - ], - [ - { - "node": "SET instance_url", - "type": "main", - "index": 0 - } - ] - ] - }, - "When viewed in a browser": { - "main": [ - [ - { - "node": "GET all workflows", - "type": "main", - "index": 0 - } - ] - ] - }, - "Exclude missing workflows": { - "main": [ - [ - { - "node": "Count callers and identify new callers", - "type": "main", - "index": 0 - } - ] - ] - }, - "Exclude uncalled workflows": { - "main": [ - [ - { - "node": "GET workflow(s)", - "type": "main", - "index": 0 - } - ] - ] - }, - "List callers of subworkflows": { - "main": [ - [ - { - "node": "Exclude uncalled workflows", - "type": "main", - "index": 0 - } - ] - ] - }, - "Return dependency graph data": { - "main": [ - [ - { - "node": "Loop through workflows", - "type": "main", - "index": 0 - } - ] - ] - }, - "Create tag id:name dictionary": { - "main": [ - [ - { - "node": "Retrieve tag ids and names from dictionary", - "type": "main", - "index": 0 - } - ] - ] - }, - "When this workflow is activated": { - "main": [ - [ - { - "node": "GET all workflows", - "type": "main", - "index": 0 - } - ] - ] - }, - "Split out new callers as new tags": { - "main": [ - [ - { - "node": "Create new tags", - "type": "main", - "index": 0 - } - ] - ] - }, - "Return original pass through values": { - "main": [ - [ - { - "node": "Merge", - "type": "main", - "index": 0 - } - ] - ] - }, - "Count callers and identify new callers": { - "main": [ - [ - { - "node": "Loop through workflows", - "type": "main", - "index": 0 - } - ] - ] - }, - "Remove existing tags from new_callers list": { - "main": [ - [ - { - "node": "If any new callers", - "type": "main", - "index": 0 - } - ] - ] - }, - "Retrieve tag ids and names from dictionary": { - "main": [ - [ - { - "node": "Update workflow tags", - "type": "main", - "index": 0 - } - ] - ] - }, - "Combine dependency graph values into labels": { - "main": [ - [ - { - "node": "Visualize subworkflow dependency graph", - "type": "main", - "index": 0 - } - ] - ] - }, - "Format workflow relationship data for rendering": { - "main": [ - [ - { - "node": "Visualize dependency graph with MermaidJS", - "type": "main", - "index": 0 - } - ] - ] - } - } -} \ No newline at end of file diff --git a/workflows/Spot Workplace Discrimination Patterns with AI.json b/workflows/Spot Workplace Discrimination Patterns with AI.json deleted file mode 100644 index c2ebdb6..0000000 --- a/workflows/Spot Workplace Discrimination Patterns with AI.json +++ /dev/null @@ -1,1850 +0,0 @@ -{ - "id": "vzU9QRZsHcyRsord", - "meta": { - "instanceId": "a9f3b18652ddc96459b459de4fa8fa33252fb820a9e5a1593074f3580352864a", - "templateCredsSetupCompleted": true - }, - "name": "Spot Workplace Discrimination Patterns with AI", - "tags": [ - { - "id": "76EYz9X3GU4PtgSS", - "name": "human_resources", - "createdAt": "2025-01-30T18:52:17.614Z", - "updatedAt": "2025-01-30T18:52:17.614Z" - }, - { - "id": "ey2Mx4vNaV8cKvao", - "name": "openai", - "createdAt": "2024-12-23T07:10:13.400Z", - "updatedAt": "2024-12-23T07:10:13.400Z" - } - ], - "nodes": [ - { - "id": "b508ab50-158a-4cbf-a52e-f53e1804e770", - "name": "When clicking \u2018Test workflow\u2019", - "type": "n8n-nodes-base.manualTrigger", - "position": [ - 280, - 380 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "11a1a2d5-a274-44f7-97ca-5666a59fcb31", - "name": "OpenAI Chat Model1", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 2220, - 800 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "395f7b67-c914-4aae-8727-0573fdbfc6ad", - "name": "OpenAI Chat Model2", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 2220, - 380 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "6ab194a9-b869-4296-aea9-19afcbffc0d7", - "name": "Merge", - "type": "n8n-nodes-base.merge", - "position": [ - 2940, - 600 - ], - "parameters": { - "mode": "combine", - "options": {}, - "combineBy": "combineByPosition" - }, - "typeVersion": 3 - }, - { - "id": "1eba1dd7-a164-4c70-8c75-759532bd16a0", - "name": "OpenAI Chat Model", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 3840, - 420 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "f25f1b07-cded-4ca7-9655-8b8f463089ab", - "name": "SET company_name", - "type": "n8n-nodes-base.set", - "position": [ - 540, - 380 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "dd256ef7-013c-4769-8580-02c2d902d0b2", - "name": "company_name", - "type": "string", - "value": "=Twilio" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "87264a93-ab97-4e39-8d40-43365189f704", - "name": "Define dictionary of demographic keys", - "type": "n8n-nodes-base.set", - "position": [ - 740, - 380 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "6ae671be-45d0-4a94-a443-2f1d4772d31b", - "name": "asian", - "type": "string", - "value": "Asian" - }, - { - "id": "6c93370c-996c-44a6-a34c-4cd3baeeb846", - "name": "hispanic", - "type": "string", - "value": "Hispanic or Latinx" - }, - { - "id": "dee79039-6051-4e9d-98b5-63a07d30f6b0", - "name": "white", - "type": "string", - "value": "White" - }, - { - "id": "08d42380-8397-412f-8459-7553e9309b5d", - "name": "pacific_islander", - "type": "string", - "value": "Native Hawaiian or other Pacific Islander" - }, - { - "id": "09e8ebc5-e7e7-449a-9036-9b9b54cdc828", - "name": "black", - "type": "string", - "value": "Black or African American" - }, - { - "id": "39e910f8-3a8b-4233-a93a-3c5693e808c6", - "name": "middle_eastern", - "type": "string", - "value": "Middle Eastern" - }, - { - "id": "169b3471-efa0-476e-aa83-e3f717c568f1", - "name": "indigenous", - "type": "string", - "value": "Indigenous American or Native Alaskan" - }, - { - "id": "b6192296-4efa-4af5-ae02-1e31d28aae90", - "name": "male", - "type": "string", - "value": "Men" - }, - { - "id": "4b322294-940c-459d-b083-8e91e38193f7", - "name": "female", - "type": "string", - "value": "Women" - }, - { - "id": "1940eef0-6b76-4a26-9d8f-7c8536fbcb1b", - "name": "trans", - "type": "string", - "value": "Transgender and/or Non-Binary" - }, - { - "id": "3dba3e18-2bb1-4078-bde9-9d187f9628dd", - "name": "hetero", - "type": "string", - "value": "Heterosexual" - }, - { - "id": "9b7d10ad-1766-4b18-a230-3bd80142b48c", - "name": "lgbtqia", - "type": "string", - "value": "LGBTQ+" - }, - { - "id": "458636f8-99e8-4245-9950-94e4cf68e371", - "name": "nondisabled", - "type": "string", - "value": "Non-Disabled" - }, - { - "id": "a466e258-7de1-4453-a126-55f780094236", - "name": "disabled", - "type": "string", - "value": "People with Disabilities" - }, - { - "id": "98735266-0451-432f-be7c-efcb09512cb1", - "name": "caregiver", - "type": "string", - "value": "Caregivers" - }, - { - "id": "ebe2353c-9ff5-47bc-8c11-b66d3436f5b4", - "name": "parent", - "type": "string", - "value": "Parents/Guardians" - }, - { - "id": "ab51c80c-d81d-41ab-94d9-c0a263743c17", - "name": "nonparent", - "type": "string", - "value": "Not a Parent or Caregiver" - }, - { - "id": "cb7df429-c600-43f4-aa7e-dbc2382a85a0", - "name": "nonveteran", - "type": "string", - "value": "Non-Veterans" - }, - { - "id": "dffbdb13-189a-462d-83d1-c5ec39a17d41", - "name": "veteran", - "type": "string", - "value": "Veterans" - } - ] - }, - "includeOtherFields": true - }, - "typeVersion": 3.4 - }, - { - "id": "862f1c77-44a8-4d79-abac-33351ebb731b", - "name": "ScrapingBee Search Glassdoor", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 940, - 380 - ], - "parameters": { - "url": "https://app.scrapingbee.com/api/v1", - "options": {}, - "sendQuery": true, - "authentication": "genericCredentialType", - "genericAuthType": "httpQueryAuth", - "queryParameters": { - "parameters": [ - { - "name": "url", - "value": "=https://www.glassdoor.com/Search/results.htm?keyword={{ $json.company_name.toLowerCase().urlEncode() }}" - }, - { - "name": "premium_proxy", - "value": "true" - }, - { - "name": "block_resources", - "value": "false" - }, - { - "name": "stealth_proxy", - "value": "true" - } - ] - } - }, - "credentials": { - "httpQueryAuth": { - "id": "XXXXXX", - "name": "ScrapingBee Query Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "4c9bf05e-9c50-4895-b20b-b7c329104615", - "name": "Extract company url path", - "type": "n8n-nodes-base.html", - "position": [ - 1140, - 380 - ], - "parameters": { - "options": {}, - "operation": "extractHtmlContent", - "extractionValues": { - "values": [ - { - "key": "url_path", - "attribute": "href", - "cssSelector": "body main div a", - "returnValue": "attribute" - } - ] - } - }, - "typeVersion": 1.2 - }, - { - "id": "d20bb0e7-4ca7-41d0-a3e9-41abc811b064", - "name": "ScrapingBee GET company page contents", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 1340, - 380 - ], - "parameters": { - "url": "https://app.scrapingbee.com/api/v1", - "options": {}, - "sendQuery": true, - "authentication": "genericCredentialType", - "genericAuthType": "httpQueryAuth", - "queryParameters": { - "parameters": [ - { - "name": "url", - "value": "=https://www.glassdoor.com{{ $json.url_path }}" - }, - { - "name": "premium_proxy", - "value": "true" - }, - { - "name": "block_resources", - "value": "false" - }, - { - "name": "stealth_proxy", - "value": "true" - } - ] - } - }, - "credentials": { - "httpQueryAuth": { - "id": "XXXXXX", - "name": "ScrapingBee Query Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "fce70cab-8ce3-4ce2-b040-ce80d66b1e62", - "name": "Extract reviews page url path", - "type": "n8n-nodes-base.html", - "position": [ - 1540, - 380 - ], - "parameters": { - "options": {}, - "operation": "extractHtmlContent", - "extractionValues": { - "values": [ - { - "key": "url_path", - "attribute": "href", - "cssSelector": "#reviews a", - "returnValue": "attribute" - } - ] - } - }, - "typeVersion": 1.2 - }, - { - "id": "d2e7fee9-e3d4-42bf-8be6-38b352371273", - "name": "ScrapingBee GET Glassdoor Reviews Content", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 1760, - 380 - ], - "parameters": { - "url": "https://app.scrapingbee.com/api/v1", - "options": {}, - "sendQuery": true, - "authentication": "genericCredentialType", - "genericAuthType": "httpQueryAuth", - "queryParameters": { - "parameters": [ - { - "name": "url", - "value": "=https://www.glassdoor.com{{ $json.url_path }}" - }, - { - "name": "premium_proxy", - "value": "True" - }, - { - "name": "block_resources", - "value": "False" - }, - { - "name": "stealth_proxy", - "value": "true" - } - ] - } - }, - "credentials": { - "httpQueryAuth": { - "id": "XXXXXX", - "name": "ScrapingBee Query Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "0c322823-0569-4bd5-9c4e-af3de0f8d7b4", - "name": "Extract Overall Review Summary", - "type": "n8n-nodes-base.html", - "position": [ - 1980, - 260 - ], - "parameters": { - "options": {}, - "operation": "extractHtmlContent", - "extractionValues": { - "values": [ - { - "key": "review_summary", - "cssSelector": "div[data-test=\"review-summary\"]", - "returnValue": "html" - } - ] - } - }, - "typeVersion": 1.2 - }, - { - "id": "851305ba-0837-4be9-943d-7282e8d74aee", - "name": "Extract Demographics Module", - "type": "n8n-nodes-base.html", - "position": [ - 1980, - 520 - ], - "parameters": { - "options": {}, - "operation": "extractHtmlContent", - "extractionValues": { - "values": [ - { - "key": "demographics_content", - "cssSelector": "div[data-test=\"demographics-module\"]", - "returnValue": "html" - } - ] - } - }, - "typeVersion": 1.2 - }, - { - "id": "cf9a6ee2-53b5-4fbf-a36c-4b9dab53b795", - "name": "Extract overall ratings and distribution percentages", - "type": "@n8n/n8n-nodes-langchain.informationExtractor", - "position": [ - 2200, - 200 - ], - "parameters": { - "text": "={{ $json.review_summary }}", - "options": {}, - "attributes": { - "attributes": [ - { - "name": "average_rating", - "type": "number", - "required": true, - "description": "The overall average rating for this company." - }, - { - "name": "total_number_of_reviews", - "type": "number", - "required": true, - "description": "The total number of reviews for this company." - }, - { - "name": "5_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 5 star reviews" - }, - { - "name": "4_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 4 star reviews" - }, - { - "name": "3_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 3 star reviews" - }, - { - "name": "2_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 2 star reviews" - }, - { - "name": "1_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 1 star reviews" - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "ae164f6e-04e7-4d8b-951e-a17085956f4b", - "name": "Extract demographic distributions", - "type": "@n8n/n8n-nodes-langchain.informationExtractor", - "position": [ - 2200, - 620 - ], - "parameters": { - "text": "={{ $json.demographics_content }}", - "options": { - "systemPromptTemplate": "You are an expert extraction algorithm.\nOnly extract relevant information from the text.\nIf you do not know the value of an attribute asked to extract, you may use 0 for the attribute's value." - }, - "attributes": { - "attributes": [ - { - "name": "asian_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as asian." - }, - { - "name": "asian_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as asian." - }, - { - "name": "hispanic_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as hispanic." - }, - { - "name": "hispanic_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as hispanic." - }, - { - "name": "white_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as white." - }, - { - "name": "white_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as white." - }, - { - "name": "pacific_islander_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as native hawaiian or pacific islander." - }, - { - "name": "pacific_islander_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as native hawaiian or pacific islander." - }, - { - "name": "black_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as black." - }, - { - "name": "black_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as black." - }, - { - "name": "middle_eastern_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as middle eastern." - }, - { - "name": "middle_eastern_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as middle_eastern." - }, - { - "name": "indigenous_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as indigenous american or native alaskan." - }, - { - "name": "indigenous_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as indigenous american or native alaskan." - }, - { - "name": "male_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as men." - }, - { - "name": "male_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as men." - }, - { - "name": "female_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as women." - }, - { - "name": "female_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as women." - }, - { - "name": "trans_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as transgender and/or non-binary." - }, - { - "name": "trans_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as trans and/or non-binary." - }, - { - "name": "hetero_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as heterosexual." - }, - { - "name": "hetero_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as heterosexual." - }, - { - "name": "lgbtqia_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as lgbtqia+." - }, - { - "name": "lgbtqia_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as lgbtqia+." - }, - { - "name": "nondisabled_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as non-disabled." - }, - { - "name": "nondisabled_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as non-disabled." - }, - { - "name": "disabled_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as people with disabilities." - }, - { - "name": "disabled_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as people with disabilities." - }, - { - "name": "caregiver_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as caregivers." - }, - { - "name": "caregiver_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as caregivers." - }, - { - "name": "parent_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as parents/guardians." - }, - { - "name": "parent_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as parents/guardians." - }, - { - "name": "nonparent_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as not a parent or caregiver." - }, - { - "name": "nonparent_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as not a parent or guardian." - }, - { - "name": "nonveteran_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as non-veterans." - }, - { - "name": "nonveteran_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as non-veterans." - }, - { - "name": "veteran_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as veterans." - }, - { - "name": "veteran_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as veterans." - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "c8d9e45c-7d41-47bd-b9a9-0fa70de5d154", - "name": "Define contributions to variance", - "type": "n8n-nodes-base.set", - "position": [ - 2560, - 200 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "7360b2c2-1e21-45de-8d1a-e72b8abcb56b", - "name": "contribution_to_variance.5_star", - "type": "number", - "value": "={{ ($json.output['5_star_distribution_percentage'] / 100) * Math.pow(5 - $json.output.average_rating,2) }}" - }, - { - "id": "acdd308a-fa33-4e33-b71b-36b9441bfa06", - "name": "contribution_to_variance.4_star", - "type": "number", - "value": "={{ ($json.output['4_star_distribution_percentage'] / 100) * Math.pow(4 - $json.output.average_rating,2) }}" - }, - { - "id": "376818f3-d429-4abe-8ece-e8e9c5585826", - "name": "contribution_to_variance.3_star", - "type": "number", - "value": "={{ ($json.output['3_star_distribution_percentage'] / 100) * Math.pow(3 - $json.output.average_rating,2) }}" - }, - { - "id": "620d5c37-8b93-4d39-9963-b7ce3a7f431e", - "name": "contribution_to_variance.2_star", - "type": "number", - "value": "={{ ($json.output['2_star_distribution_percentage'] / 100) * Math.pow(2 - $json.output.average_rating,2) }}" - }, - { - "id": "76357980-4f9b-4b14-be68-6498ba25af67", - "name": "contribution_to_variance.1_star", - "type": "number", - "value": "={{ ($json.output['1_star_distribution_percentage'] / 100) * Math.pow(1 - $json.output.average_rating,2) }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "8ea03017-d5d6-46ef-a5f1-dae4372f6256", - "name": "Set variance and std_dev", - "type": "n8n-nodes-base.set", - "position": [ - 2740, - 200 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "3217d418-f1b0-45ff-9f9a-6e6145cc29ca", - "name": "variance", - "type": "number", - "value": "={{ $json.contribution_to_variance.values().sum() }}" - }, - { - "id": "acdb9fea-15ec-46ed-bde9-073e93597f17", - "name": "average_rating", - "type": "number", - "value": "={{ $('Extract overall ratings and distribution percentages').item.json.output.average_rating }}" - }, - { - "id": "1f3a8a29-4bd4-4b40-8694-c74a0285eadb", - "name": "total_number_of_reviews", - "type": "number", - "value": "={{ $('Extract overall ratings and distribution percentages').item.json.output.total_number_of_reviews }}" - }, - { - "id": "1906c796-1964-446b-8b56-d856269da938", - "name": "std_dev", - "type": "number", - "value": "={{ Math.sqrt($json.contribution_to_variance.values().sum()) }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "0570d531-8480-4446-8f02-18640b4b891e", - "name": "Calculate P-Scores", - "type": "n8n-nodes-base.code", - "position": [ - 3340, - 440 - ], - "parameters": { - "jsCode": "// Approximate CDF for standard normal distribution\nfunction normSDist(z) {\n const t = 1 / (1 + 0.3275911 * Math.abs(z));\n const d = 0.254829592 * t - 0.284496736 * t * t + 1.421413741 * t * t * t - 1.453152027 * t * t * t * t + 1.061405429 * t * t * t * t * t;\n return 0.5 * (1 + Math.sign(z) * d * Math.exp(-z * z / 2));\n}\n\nfor (const item of $input.all()) {\n if (!item.json.population_analysis.p_scores) {\n item.json.population_analysis.p_scores = {};\n }\n\n for (const score of Object.keys(item.json.population_analysis.z_scores)) {\n // Check if review count exists and is greater than zero\n if (item.json.population_analysis.review_count[score] > 0) {\n // Apply the p_score formula: 2 * NORM.S.DIST(-ABS(z_score))\n const p_score = 2 * normSDist(-Math.abs(item.json.population_analysis.z_scores[score]));\n\n // Store the calculated p_score\n item.json.population_analysis.p_scores[score] = p_score;\n } else {\n // Remove z_scores, effect_sizes, and p_scores for groups with no reviews\n delete item.json.population_analysis.z_scores[score];\n delete item.json.population_analysis.effect_sizes[score];\n delete item.json.population_analysis.p_scores[score];\n }\n }\n}\n\nreturn $input.all();" - }, - "typeVersion": 2 - }, - { - "id": "0bdb9732-67ef-440d-bdd2-42c4f64ff6b6", - "name": "Sort Effect Sizes", - "type": "n8n-nodes-base.set", - "position": [ - 3540, - 440 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "61cf92ba-bc4e-40b8-a234-9b993fd24019", - "name": "population_analysis.effect_sizes", - "type": "object", - "value": "={{ Object.fromEntries(Object.entries($json.population_analysis.effect_sizes).sort(([,a],[,b]) => a-b )) }}" - } - ] - }, - "includeOtherFields": true - }, - "typeVersion": 3.4 - }, - { - "id": "fd9026ef-e993-410a-87d6-40a3ad10b7a7", - "name": "Calculate Z-Scores and Effect Sizes", - "type": "n8n-nodes-base.set", - "position": [ - 3140, - 600 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "790a53e8-5599-45d3-880e-ab1ad7d165d2", - "name": "population_analysis.z_scores.asian", - "type": "number", - "value": "={{ ($json.output.asian_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.asian_total_number_of_reviews)) }}" - }, - { - "id": "ebd61097-8773-45b9-a8e6-cdd840d73650", - "name": "population_analysis.effect_sizes.asian", - "type": "number", - "value": "={{ ($json.output.asian_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "627b1293-efdc-485a-83c8-bd332d6dc225", - "name": "population_analysis.z_scores.hispanic", - "type": "number", - "value": "={{ ($json.output.hispanic_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.hispanic_total_number_of_reviews)) }}" - }, - { - "id": "822028d0-e94f-4cf7-9e13-8f8cc5c72ec0", - "name": "population_analysis.z_scores.white", - "type": "number", - "value": "={{ ($json.output.white_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.white_total_number_of_reviews)) }}" - }, - { - "id": "d32321f9-0fcf-4e54-9059-c3fd5a901ce0", - "name": "population_analysis.z_scores.pacific_islander", - "type": "number", - "value": "={{ ($json.output.pacific_islander_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.pacific_islander_total_number_of_reviews)) }}" - }, - { - "id": "e212d683-247f-45c4-9668-c290230a10ed", - "name": "population_analysis.z_scores.black", - "type": "number", - "value": "={{ ($json.output.black_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.black_total_number_of_reviews)) }}" - }, - { - "id": "882049c3-eb81-4c09-af0c-5c79b0ef0154", - "name": "population_analysis.z_scores.middle_eastern", - "type": "number", - "value": "={{ ($json.output.middle_eastern_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.middle_eastern_total_number_of_reviews)) }}" - }, - { - "id": "9bdc187f-3d8d-4030-9143-479eff441b7e", - "name": "population_analysis.z_scores.indigenous", - "type": "number", - "value": "={{ ($json.output.indigenous_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.indigenous_total_number_of_reviews)) }}" - }, - { - "id": "0cf11453-dbae-4250-a01a-c98e35aab224", - "name": "population_analysis.z_scores.male", - "type": "number", - "value": "={{ ($json.output.male_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.male_total_number_of_reviews)) }}" - }, - { - "id": "35a18fbc-7c2c-40fe-829d-2fffbdb13bb8", - "name": "population_analysis.z_scores.female", - "type": "number", - "value": "={{ ($json.output.female_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.female_total_number_of_reviews)) }}" - }, - { - "id": "a6e17c1b-a89b-4c05-8184-10f7248c159f", - "name": "population_analysis.z_scores.trans", - "type": "number", - "value": "={{ ($json.output.trans_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.trans_total_number_of_reviews)) }}" - }, - { - "id": "5e7dbccf-3011-4dba-863c-5390c1ee9e50", - "name": "population_analysis.z_scores.hetero", - "type": "number", - "value": "={{ ($json.output.hetero_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.hetero_total_number_of_reviews)) }}" - }, - { - "id": "1872152f-2c7e-4c24-bcd5-e2777616bfe2", - "name": "population_analysis.z_scores.lgbtqia", - "type": "number", - "value": "={{ ($json.output.lgbtqia_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.lgbtqia_total_number_of_reviews)) }}" - }, - { - "id": "91b2cb00-173e-421a-929a-51d2a6654767", - "name": "population_analysis.z_scores.nondisabled", - "type": "number", - "value": "={{ ($json.output.nondisabled_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.nondisabled_total_number_of_reviews)) }}" - }, - { - "id": "8bb7429e-0500-482c-8e8d-d2c63733ffe1", - "name": "population_analysis.z_scores.disabled", - "type": "number", - "value": "={{ ($json.output.disabled_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.disabled_total_number_of_reviews)) }}" - }, - { - "id": "89f00d0f-80db-4ad9-bf60-9385aa3d915b", - "name": "population_analysis.z_scores.caregiver", - "type": "number", - "value": "={{ ($json.output.caregiver_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.caregiver_total_number_of_reviews)) }}" - }, - { - "id": "0bb2b96c-d882-4ac1-9432-9fce06b26cf5", - "name": "population_analysis.z_scores.parent", - "type": "number", - "value": "={{ ($json.output.parent_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.parent_total_number_of_reviews)) }}" - }, - { - "id": "9aae7169-1a25-4fab-b940-7f2cd7ef39d9", - "name": "population_analysis.z_scores.nonparent", - "type": "number", - "value": "={{ ($json.output.nonparent_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.nonparent_total_number_of_reviews)) }}" - }, - { - "id": "aac189a0-d6fc-4581-a15d-3e75a0cb370a", - "name": "population_analysis.z_scores.nonveteran", - "type": "number", - "value": "={{ ($json.output.nonveteran_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.nonveteran_total_number_of_reviews)) }}" - }, - { - "id": "d40f014a-9c1d-4aea-88ac-d8a3de143931", - "name": "population_analysis.z_scores.veteran", - "type": "number", - "value": "={{ ($json.output.veteran_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.veteran_total_number_of_reviews)) }}" - }, - { - "id": "67e0394f-6d55-4e80-8a7d-814635620b1d", - "name": "population_analysis.effect_sizes.hispanic", - "type": "number", - "value": "={{ ($json.output.hispanic_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "65cd3a22-2c97-4da1-8fcc-cc1af39118f2", - "name": "population_analysis.effect_sizes.white", - "type": "number", - "value": "={{ ($json.output.white_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "a03bdf0f-e294-4a01-bb08-ddc16e9997a5", - "name": "population_analysis.effect_sizes.pacific_islander", - "type": "number", - "value": "={{ ($json.output.pacific_islander_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "b0bdc40e-ed5f-475b-9d8b-8cf5beff7002", - "name": "population_analysis.effect_sizes.black", - "type": "number", - "value": "={{ ($json.output.black_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "45cac3f0-7270-4fa4-8fc4-94914245a77d", - "name": "population_analysis.effect_sizes.middle_eastern", - "type": "number", - "value": "={{ ($json.output.middle_eastern_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "cf5b7650-8766-45f6-8241-49aea62bf619", - "name": "population_analysis.effect_sizes.indigenous", - "type": "number", - "value": "={{ ($json.output.indigenous_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "7c6a8d38-02b7-47a1-af44-5eebfb4140ec", - "name": "population_analysis.effect_sizes.male", - "type": "number", - "value": "={{ ($json.output.male_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "4bf3dba9-4d07-4315-83ce-5fba288a00c9", - "name": "population_analysis.effect_sizes.female", - "type": "number", - "value": "={{ ($json.output.female_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "d5e980b8-d7a8-4d4c-bcd9-fd9cbd20c729", - "name": "population_analysis.effect_sizes.trans", - "type": "number", - "value": "={{ ($json.output.trans_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "2c8271c1-b612-4292-9d48-92c342b83727", - "name": "population_analysis.effect_sizes.hetero", - "type": "number", - "value": "={{ ($json.output.hetero_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "996f2ea0-2e46-424b-9797-2d58fd56b1d3", - "name": "population_analysis.effect_sizes.lgbtqia", - "type": "number", - "value": "={{ ($json.output.lgbtqia_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "8c987b6e-764d-422e-82de-00bd89269b22", - "name": "population_analysis.effect_sizes.nondisabled", - "type": "number", - "value": "={{ ($json.output.nondisabled_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "ab796bb7-06ff-4282-b4b3-eefd129c743e", - "name": "population_analysis.effect_sizes.disabled", - "type": "number", - "value": "={{ ($json.output.disabled_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "a17bf413-a098-4f24-8162-821a6a0ddb5e", - "name": "population_analysis.effect_sizes.caregiver", - "type": "number", - "value": "={{ ($json.output.caregiver_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "99911e1e-06e8-4bbd-915d-b92b8b37b374", - "name": "population_analysis.effect_sizes.parent", - "type": "number", - "value": "={{ ($json.output.parent_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "4ddf729b-361e-4d81-a67c-b6c18509e60b", - "name": "population_analysis.effect_sizes.nonparent", - "type": "number", - "value": "={{ ($json.output.nonparent_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "725b8abb-7f72-45fc-a0c0-0e0a4f2cb131", - "name": "population_analysis.effect_sizes.nonveteran", - "type": "number", - "value": "={{ ($json.output.nonveteran_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "20e54fa5-2faa-4134-90e5-81224ec9659e", - "name": "population_analysis.effect_sizes.veteran", - "type": "number", - "value": "={{ ($json.output.veteran_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "2cc6465a-3a1c-4eb5-9e5a-72d41049d81e", - "name": "population_analysis.review_count.asian", - "type": "number", - "value": "={{ $json.output.asian_total_number_of_reviews }}" - }, - { - "id": "0a5f6aae-ba21-47b5-8af8-fec2256e4df6", - "name": "population_analysis.review_count.hispanic", - "type": "number", - "value": "={{ $json.output.hispanic_total_number_of_reviews }}" - }, - { - "id": "ae124587-7e24-4c1a-a002-ed801f859c30", - "name": "population_analysis.review_count.pacific_islander", - "type": "number", - "value": "={{ $json.output.pacific_islander_total_number_of_reviews }}" - }, - { - "id": "fc790196-ca8e-4069-a093-87a413ebbf3e", - "name": "population_analysis.review_count.black", - "type": "number", - "value": "={{ $json.output.black_total_number_of_reviews }}" - }, - { - "id": "7fd72701-781e-4e33-b000-174a853b172b", - "name": "population_analysis.review_count.middle_eastern", - "type": "number", - "value": "={{ $json.output.middle_eastern_total_number_of_reviews }}" - }, - { - "id": "3751e7da-11a7-4af3-8aa6-1c6d53bcf27d", - "name": "population_analysis.review_count.indigenous", - "type": "number", - "value": "={{ $json.output.indigenous_total_number_of_reviews }}" - }, - { - "id": "9ee0cac9-d2dd-4ba0-90ee-b2cdd22d9b77", - "name": "population_analysis.review_count.male", - "type": "number", - "value": "={{ $json.output.male_total_number_of_reviews }}" - }, - { - "id": "ae7fcdc7-d373-4c24-9a65-94bd2b5847a8", - "name": "population_analysis.review_count.female", - "type": "number", - "value": "={{ $json.output.female_total_number_of_reviews }}" - }, - { - "id": "3f53d065-269f-425a-b27d-dc5a3dbb6141", - "name": "population_analysis.review_count.trans", - "type": "number", - "value": "={{ $json.output.trans_total_number_of_reviews }}" - }, - { - "id": "d15e976e-7599-4df0-9e65-8047b7a4cda8", - "name": "population_analysis.review_count.hetero", - "type": "number", - "value": "={{ $json.output.hetero_total_number_of_reviews }}" - }, - { - "id": "c8b786d3-a980-469f-bf0e-de70ad44f0ea", - "name": "population_analysis.review_count.lgbtqia", - "type": "number", - "value": "={{ $json.output.lgbtqia_total_number_of_reviews }}" - }, - { - "id": "e9429215-0858-4482-964a-75de7978ecbb", - "name": "population_analysis.review_count.nondisabled", - "type": "number", - "value": "={{ $json.output.nondisabled_total_number_of_reviews }}" - }, - { - "id": "2c6e53c4-eab1-42aa-b956-ee882832f569", - "name": "population_analysis.review_count.disabled", - "type": "number", - "value": "={{ $json.output.disabled_total_number_of_reviews }}" - }, - { - "id": "b5edfa25-ab11-4b94-9670-4d5589a62498", - "name": "population_analysis.review_count.caregiver", - "type": "number", - "value": "={{ $json.output.caregiver_total_number_of_reviews }}" - }, - { - "id": "41084e96-c42f-4bb0-ac1a-883b46537fca", - "name": "population_analysis.review_count.parent", - "type": "number", - "value": "={{ $json.output.parent_total_number_of_reviews }}" - }, - { - "id": "96496a38-9311-4ade-bd2f-2943d1d92314", - "name": "population_analysis.review_count.nonparent", - "type": "number", - "value": "={{ $json.output.nonparent_total_number_of_reviews }}" - }, - { - "id": "5071771d-5f41-43cb-a8ce-e4e40ed3519b", - "name": "population_analysis.review_count.nonveteran", - "type": "number", - "value": "={{ $json.output.nonveteran_total_number_of_reviews }}" - }, - { - "id": "2358e782-70da-4964-b625-5fe1946b5250", - "name": "population_analysis.review_count.veteran", - "type": "number", - "value": "={{ $json.output.veteran_total_number_of_reviews }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "85536931-839a-476b-b0dd-fa6d01c6d5c1", - "name": "Format dataset for scatterplot", - "type": "n8n-nodes-base.code", - "position": [ - 3340, - 760 - ], - "parameters": { - "jsCode": "// Iterate through the input data and format the dataset for QuickChart\nfor (const item of $input.all()) {\n // Ensure the data object exists and initialize datasets\n item.json.data = {\n datasets: []\n };\n\n const z_scores = item.json.population_analysis.z_scores;\n const effect_sizes = item.json.population_analysis.effect_sizes;\n const review_count = item.json.population_analysis.review_count;\n\n // Ensure z_scores, effect_sizes, and review_count are defined and are objects\n if (z_scores && effect_sizes && review_count && typeof z_scores === 'object' && typeof effect_sizes === 'object' && typeof review_count === 'object') {\n // Initialize the dataset object\n const dataset = {\n label: 'Demographics Data',\n data: []\n };\n\n // Iterate through the demographic keys\n for (const key in z_scores) {\n // Check if review count for the demographic is greater than 0\n if (z_scores.hasOwnProperty(key) && effect_sizes.hasOwnProperty(key) && review_count[key] > 0) {\n\n // Add each demographic point to the dataset\n dataset.data.push({\n x: z_scores[key], // x = z_score\n y: effect_sizes[key], // y = effect_size\n label: $('Define dictionary of demographic keys').first().json[key],\n });\n }\n }\n\n // Only add the dataset if it contains data\n if (dataset.data.length > 0) {\n item.json.data.datasets.push(dataset);\n }\n\n delete item.json.population_analysis\n }\n}\n\n// Return the updated input with the data object containing datasets and labels\nreturn $input.all();\n" - }, - "typeVersion": 2 - }, - { - "id": "957b9f6c-7cf8-4ec6-aec7-a7d59ed3a4ad", - "name": "Specify additional parameters for scatterplot", - "type": "n8n-nodes-base.set", - "position": [ - 3540, - 760 - ], - "parameters": { - "options": { - "ignoreConversionErrors": false - }, - "assignments": { - "assignments": [ - { - "id": "5cd507f6-6835-4d2e-8329-1b5d24a3fc15", - "name": "type", - "type": "string", - "value": "scatter" - }, - { - "id": "80b6f981-e3c7-4c6e-a0a1-f30d028fe15e", - "name": "options", - "type": "object", - "value": "={\n \"title\": {\n \"display\": true,\n \"position\": \"top\",\n \"fontSize\": 12,\n \"fontFamily\": \"sans-serif\",\n \"fontColor\": \"#666666\",\n \"fontStyle\": \"bold\",\n \"padding\": 10,\n \"lineHeight\": 1.2,\n \"text\": \"{{ $('SET company_name').item.json.company_name }} Workplace Population Bias\"\n },\n \"legend\": {\n \"display\": false\n },\n \"scales\": {\n \"xAxes\": [\n {\n \"scaleLabel\": {\n \"display\": true,\n \"labelString\": \"Z-Score\",\n \"fontColor\": \"#666666\",\n \"fontSize\": 12,\n \"fontFamily\": \"sans-serif\"\n }\n }\n ],\n \"yAxes\": [\n {\n \"scaleLabel\": {\n \"display\": true,\n \"labelString\": \"Effect Score\",\n \"fontColor\": \"#666666\",\n \"fontSize\": 12,\n \"fontFamily\": \"sans-serif\"\n }\n }\n ]\n },\n \"plugins\": {\n \"datalabels\": {\n \"display\": true,\n \"align\": \"top\",\n \"anchor\": \"center\",\n \"backgroundColor\": \"#eee\",\n \"borderColor\": \"#ddd\",\n \"borderRadius\": 6,\n \"borderWidth\": 1,\n \"padding\": 4,\n \"color\": \"#000\",\n \"font\": {\n \"family\": \"sans-serif\",\n \"size\": 10,\n \"style\": \"normal\"\n }\n }\n }\n }" - } - ] - }, - "includeOtherFields": true - }, - "typeVersion": 3.4 - }, - { - "id": "a937132c-43fc-4fa0-ae35-885da89e51d1", - "name": "Quickchart Scatterplot", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 3740, - 760 - ], - "parameters": { - "url": "https://quickchart.io/chart", - "options": {}, - "sendQuery": true, - "queryParameters": { - "parameters": [ - { - "name": "c", - "value": "={{ $json.toJsonString() }}" - }, - { - "name": "Content-Type", - "value": "application/json" - }, - { - "name": "encoding", - "value": "url" - } - ] - } - }, - "typeVersion": 4.2 - }, - { - "id": "ede1931e-bac8-4279-b3a7-5980a190e324", - "name": "QuickChart Bar Chart", - "type": "n8n-nodes-base.quickChart", - "position": [ - 3740, - 560 - ], - "parameters": { - "data": "={{ $json.population_analysis.effect_sizes.values() }}", - "output": "bar_chart", - "labelsMode": "array", - "labelsArray": "={{ $json.population_analysis.effect_sizes.keys() }}", - "chartOptions": { - "format": "png" - }, - "datasetOptions": { - "label": "={{ $('SET company_name').item.json.company_name }} Effect Size on Employee Experience" - } - }, - "typeVersion": 1 - }, - { - "id": "6122fec0-619c-48d3-ad2c-05ed55ba2275", - "name": "Sticky Note", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 480, - 40 - ], - "parameters": { - "color": 7, - "width": 3741.593083126444, - "height": 1044.8111554136713, - "content": "# Spot Workplace Discrimination Patterns using ScrapingBee, Glassdoor, OpenAI, and QuickChart\n" - }, - "typeVersion": 1 - }, - { - "id": "5cda63e8-f31b-46f6-8cb2-41d1856ac537", - "name": "Sticky Note1", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 900, - 180 - ], - "parameters": { - "color": 4, - "width": 1237.3377621763516, - "height": 575.9439659309116, - "content": "## Use ScrapingBee to gather raw data from Glassdoor" - }, - "typeVersion": 1 - }, - { - "id": "28d247b2-9020-4280-83d2-d6583622c0b7", - "name": "Sticky Note2", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 920, - 240 - ], - "parameters": { - "color": 7, - "width": 804.3951263154196, - "height": 125.73173301324687, - "content": "### Due to javascript restrictions, a normal HTTP request cannot be used to gather user-reported details from Glassdoor. \n\nInstead, [ScrapingBee](https://www.scrapingbee.com/) offers a great tool with a very generous package of free tokens per month, which works out to roughly 4-5 runs of this workflow." - }, - "typeVersion": 1 - }, - { - "id": "d65a239c-06d2-470b-b24a-23ec00a9f148", - "name": "Sticky Note3", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2180, - 99.69933502879758 - ], - "parameters": { - "color": 5, - "width": 311.0523273992095, - "height": 843.8786512173932, - "content": "## Extract details with AI" - }, - "typeVersion": 1 - }, - { - "id": "3cffd188-62a1-43a7-a67f-548e21d2b187", - "name": "Sticky Note4", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2516.1138215303854, - 100 - ], - "parameters": { - "color": 7, - "width": 423.41585047129973, - "height": 309.71740416262054, - "content": "### Calculate variance and standard deviation from review rating distributions." - }, - "typeVersion": 1 - }, - { - "id": "b5015c07-03e3-47d4-9469-e831b2c755c0", - "name": "Sticky Note6", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 3320, - 706.46982689582 - ], - "parameters": { - "color": 5, - "width": 639.5579220386832, - "height": 242.80759628871897, - "content": "## Formatting datasets for Scatterplot" - }, - "typeVersion": 1 - }, - { - "id": "e52bb9d9-617a-46f5-b217-a6f670b6714c", - "name": "Sticky Note7", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 500, - 120 - ], - "parameters": { - "width": 356.84794255678776, - "height": 186.36110628732342, - "content": "## How this workflow works\n1. Replace ScrapingBee and OpenAI credentials\n2. Replace company_name with company of choice (workflow performs better with larger US-based organizations)\n3. Preview QuickChart data visualizations and AI data analysis" - }, - "typeVersion": 1 - }, - { - "id": "d83c07a3-04ed-418f-94f1-e70828cba8b2", - "name": "Sticky Note8", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 500, - 880 - ], - "parameters": { - "color": 6, - "width": 356.84794255678776, - "height": 181.54335665904924, - "content": "### Inspired by [Wes Medford's Medium Post](https://medium.com/@wryanmedford/an-open-letter-to-twilios-leadership-f06f661ecfb4)\n\nWes performed the initial data analysis highlighting problematic behaviors at Twilio. I wanted to try and democratize the data analysis they performed for those less technical.\n\n**Hi, Wes!**" - }, - "typeVersion": 1 - }, - { - "id": "ed0c1b4a-99fe-4a27-90bb-ac38dd20810b", - "name": "Sticky Note9", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 4020, - 880 - ], - "parameters": { - "color": 7, - "width": 847.5931795867759, - "height": 522.346478008115, - "content": "![image](https://quickchart.io/chart?c=%7B%0A%20%20%22type%22%3A%20%22scatter%22%2C%0A%20%20%22data%22%3A%20%7B%0A%20%20%20%20%22datasets%22%3A%20%5B%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%22label%22%3A%20%22Demographics%20Data%22%2C%0A%20%20%20%20%20%20%20%20%22data%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%201.1786657494327952%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%200.16190219204909295%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%200.5119796850491362%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%200.0809510960245463%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-0.9300572848378476%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.16190219204909329%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-0.42835293687811976%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.16190219204909329%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.0890856121128139%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.08095109602454664%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.7362075843299012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.16190219204909329%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-2.9142394568836774%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.971413152294559%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.2088576542791578%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.08095109602454664%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-2.5276971632072494%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.4047554801227329%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%200%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%200%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-5.504674529669168%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-1.376168632417292%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-0.8412684674574105%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.24285328807363996%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-2.896194457023989%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.32380438409818657%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.0303392409819254%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.08095109602454664%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.2670850749479952%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.08095109602454664%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%201.535939055147413%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%200.4857065761472792%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%2C%0A%20%20%20%20%22labels%22%3A%20%5B%0A%20%20%20%20%20%20%22asian%22%2C%0A%20%20%20%20%20%20%22hispanic%22%2C%0A%20%20%20%20%20%20%22black%22%2C%0A%20%20%20%20%20%20%22middle_eastern%22%2C%0A%20%20%20%20%20%20%22male%22%2C%0A%20%20%20%20%20%20%22female%22%2C%0A%20%20%20%20%20%20%22trans%22%2C%0A%20%20%20%20%20%20%22hetero%22%2C%0A%20%20%20%20%20%20%22lgbtqia%22%2C%0A%20%20%20%20%20%20%22nondisabled%22%2C%0A%20%20%20%20%20%20%22disabled%22%2C%0A%20%20%20%20%20%20%22caregiver%22%2C%0A%20%20%20%20%20%20%22parent%22%2C%0A%20%20%20%20%20%20%22nonparent%22%2C%0A%20%20%20%20%20%20%22nonveteran%22%2C%0A%20%20%20%20%20%20%22veteran%22%0A%20%20%20%20%5D%0A%20%20%7D%2C%0A%20%20%22options%22%3A%20%7B%0A%20%20%20%20%22title%22%3A%20%7B%0A%20%20%20%20%20%20%22display%22%3A%20true%2C%0A%20%20%20%20%20%20%22position%22%3A%20%22top%22%2C%0A%20%20%20%20%20%20%22fontSize%22%3A%2012%2C%0A%20%20%20%20%20%20%22fontFamily%22%3A%20%22sans-serif%22%2C%0A%20%20%20%20%20%20%22fontColor%22%3A%20%22%23666666%22%2C%0A%20%20%20%20%20%20%22fontStyle%22%3A%20%22bold%22%2C%0A%20%20%20%20%20%20%22padding%22%3A%2010%2C%0A%20%20%20%20%20%20%22lineHeight%22%3A%201.2%2C%0A%20%20%20%20%20%20%22text%22%3A%20%22Twilio%20Workplace%20Population%20Bias%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22legend%22%3A%20%7B%0A%20%20%20%20%20%20%22display%22%3A%20false%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22scales%22%3A%20%7B%0A%20%20%20%20%20%20%22xAxes%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22scaleLabel%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22display%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22labelString%22%3A%20%22Z-Score%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontColor%22%3A%20%22%23666666%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontSize%22%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontFamily%22%3A%20%22sans-serif%22%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%22yAxes%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22scaleLabel%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22display%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22labelString%22%3A%20%22Effect%20Score%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontColor%22%3A%20%22%23666666%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontSize%22%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontFamily%22%3A%20%22sans-serif%22%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%5D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22plugins%22%3A%20%7B%0A%20%20%20%20%20%20%22datalabels%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22display%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%22align%22%3A%20%22top%22%2C%0A%20%20%20%20%20%20%20%20%22anchor%22%3A%20%22center%22%2C%0A%20%20%20%20%20%20%20%20%22backgroundColor%22%3A%20%22%23eee%22%2C%0A%20%20%20%20%20%20%20%20%22borderColor%22%3A%20%22%23ddd%22%2C%0A%20%20%20%20%20%20%20%20%22borderRadius%22%3A%206%2C%0A%20%20%20%20%20%20%20%20%22borderWidth%22%3A%201%2C%0A%20%20%20%20%20%20%20%20%22padding%22%3A%204%2C%0A%20%20%20%20%20%20%20%20%22color%22%3A%20%22%23000%22%2C%0A%20%20%20%20%20%20%20%20%22font%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22family%22%3A%20%22sans-serif%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22size%22%3A%2010%2C%0A%20%20%20%20%20%20%20%20%20%20%22style%22%3A%20%22normal%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22formatter%22%3A%20function(value%2C%20context)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20idx%20%3D%20context.dataIndex%3B%0A%20%20%20%20%20%20%20%20%20%20return%20context.chart.data.labels%5Bidx%5D%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A#full-width)" - }, - "typeVersion": 1 - }, - { - "id": "7b92edf8-3a58-4931-abf4-d9c2f57cfa32", - "name": "Sticky Note10", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 3980, - 800 - ], - "parameters": { - "color": 6, - "width": 989.7621518164046, - "height": 636.6345107975716, - "content": "## Example Scatterplot output" - }, - "typeVersion": 1 - }, - { - "id": "bd6859b4-096c-401e-9bce-91e970e1afd1", - "name": "Sticky Note11", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2540, - 800 - ], - "parameters": { - "color": 6, - "width": 737.6316136259719, - "height": 444.9087184962878, - "content": "## Glossary\n**Z-Score** \u2013 A statistical measure that indicates how many standard deviations a data point is from the mean. In this analysis, a negative z-score suggests a group rates their workplace experience lower than the average, while a positive z-score suggests a better-than-average experience.\n\n**Effect Size** \u2013 A measure of the magnitude of difference between groups. Larger negative effect sizes indicate a more substantial disparity in workplace experiences for certain groups, making it useful for identifying meaningful gaps beyond just statistical significance.\n\n**P-Score (P-Value)** \u2013 The probability that the observed differences occurred by chance. A lower p-score (typically below 0.05) suggests the difference is statistically significant and unlikely to be random. In this analysis, high p-scores confirm that the disparities in ratings for marginalized groups are unlikely to be due to chance alone.\n\n### Relevance to This Analysis\nThese metrics help quantify workplace disparities among demographic groups. Z-scores show which groups report better or worse experiences, effect sizes reveal the severity of these differences, and p-scores confirm whether the disparities are statistically meaningful. This data allows for a more informed discussion about workplace equity and areas needing improvement." - }, - "typeVersion": 1 - }, - { - "id": "5af3ef87-ed4b-481e-b1ba-d44ffb7551d8", - "name": "Sticky Note12", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 4140, - 80 - ], - "parameters": { - "color": 6, - "width": 643.5995639515581, - "height": 646.0030521944287, - "content": "## Example AI Analysis (Twilio Example)\n\n### Key Takeaways\n1. **Significant Disparity Among Disabled Employees**\nDisabled employees reported the lowest average ratings, with a z-score of -5.50, indicating a far worse experience compared to their non-disabled peers. \n2. **LGBTQIA Community's Challenges**\nMembers of the LGBTQIA community showed significantly lower ratings (z-score of -2.53), suggesting they may experience a workplace environment that is less inclusive or supportive compared to others.\n3. **Transgender Experiences Are Particularly Negative**\nTransgender employees rated their experiences considerably lower (z-score of -2.91), highlighting a critical area for improvement in workplace culture and acceptance.\n4. **Veterans Report Higher Satisfaction**\nIn contrast, veterans had the highest ratings (z-score of 1.54), which could indicate a supportive environment or programs tailored to their needs.\n5. **Overall Gender Discrepancies**\nA noticeable gap exists in average ratings by gender, with female employees scoring below male employees, suggesting potential gender biases or challenges in workplace dynamics.\n\n### Employee Experiences\n#### Perceptions of Workplace Environment\nFor members of groups reporting significantly worse experiences, such as disabled, transgender, and LGBTQIA employees, the workplace may feel alienating or unwelcoming. These individuals might perceive that their contributions are undervalued or overlooked and that necessary support systems are lacking, creating a culture of exclusion rather than one of inclusivity. This feeling of being marginalized can lead to poorer engagement, higher turnover rates, and diminished overall job satisfaction, adversely impacting both employees and the organization." - }, - "typeVersion": 1 - }, - { - "id": "a39cdbe7-d6ae-4a84-98c7-52ebf98242f3", - "name": "Text Analysis of Bias Data", - "type": "@n8n/n8n-nodes-langchain.chainLlm", - "position": [ - 3720, - 280 - ], - "parameters": { - "text": "=This data compares the average rating given by different demographic groups against a baseline (the overall mean rating).\n\nObjective:\n1. Analyze the data and offer between 2 and 5 key takeaways with a title and short (one-sentence) summary.\n2. Below the key takeaways, Include a heading called \"Employee Experiences\". Under this heading, include a subheader and paragraph describing the possible perception of the workplace for members of any groups reporting significantly worse (or better) experiences than others.\n3. Ensure there are between 2-5 key takeaways and employee experiences\n\nData for analysis:\n{{ $json.population_analysis.toJsonString() }}", - "promptType": "define" - }, - "typeVersion": 1.4 - } - ], - "active": false, - "pinData": {}, - "settings": { - "executionOrder": "v1" - }, - "versionId": "ff1df786-ebaf-4ed0-aeca-1872b93ef275", - "connections": { - "Merge": { - "main": [ - [ - { - "node": "Calculate Z-Scores and Effect Sizes", - "type": "main", - "index": 0 - } - ] - ] - }, - "SET company_name": { - "main": [ - [ - { - "node": "Define dictionary of demographic keys", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model": { - "ai_languageModel": [ - [ - { - "node": "Text Analysis of Bias Data", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "Sort Effect Sizes": { - "main": [ - [ - { - "node": "QuickChart Bar Chart", - "type": "main", - "index": 0 - }, - { - "node": "Text Analysis of Bias Data", - "type": "main", - "index": 0 - } - ] - ] - }, - "Calculate P-Scores": { - "main": [ - [ - { - "node": "Sort Effect Sizes", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model1": { - "ai_languageModel": [ - [ - { - "node": "Extract demographic distributions", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model2": { - "ai_languageModel": [ - [ - { - "node": "Extract overall ratings and distribution percentages", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "Extract company url path": { - "main": [ - [ - { - "node": "ScrapingBee GET company page contents", - "type": "main", - "index": 0 - } - ] - ] - }, - "Set variance and std_dev": { - "main": [ - [ - { - "node": "Merge", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract Demographics Module": { - "main": [ - [ - { - "node": "Extract demographic distributions", - "type": "main", - "index": 0 - } - ] - ] - }, - "ScrapingBee Search Glassdoor": { - "main": [ - [ - { - "node": "Extract company url path", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract reviews page url path": { - "main": [ - [ - { - "node": "ScrapingBee GET Glassdoor Reviews Content", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract Overall Review Summary": { - "main": [ - [ - { - "node": "Extract overall ratings and distribution percentages", - "type": "main", - "index": 0 - } - ] - ] - }, - "Format dataset for scatterplot": { - "main": [ - [ - { - "node": "Specify additional parameters for scatterplot", - "type": "main", - "index": 0 - } - ] - ] - }, - "Define contributions to variance": { - "main": [ - [ - { - "node": "Set variance and std_dev", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract demographic distributions": { - "main": [ - [ - { - "node": "Merge", - "type": "main", - "index": 1 - } - ] - ] - }, - "When clicking \u2018Test workflow\u2019": { - "main": [ - [ - { - "node": "SET company_name", - "type": "main", - "index": 0 - } - ] - ] - }, - "Calculate Z-Scores and Effect Sizes": { - "main": [ - [ - { - "node": "Calculate P-Scores", - "type": "main", - "index": 0 - }, - { - "node": "Format dataset for scatterplot", - "type": "main", - "index": 0 - } - ] - ] - }, - "Define dictionary of demographic keys": { - "main": [ - [ - { - "node": "ScrapingBee Search Glassdoor", - "type": "main", - "index": 0 - } - ] - ] - }, - "ScrapingBee GET company page contents": { - "main": [ - [ - { - "node": "Extract reviews page url path", - "type": "main", - "index": 0 - } - ] - ] - }, - "ScrapingBee GET Glassdoor Reviews Content": { - "main": [ - [ - { - "node": "Extract Demographics Module", - "type": "main", - "index": 0 - }, - { - "node": "Extract Overall Review Summary", - "type": "main", - "index": 0 - } - ] - ] - }, - "Specify additional parameters for scatterplot": { - "main": [ - [ - { - "node": "Quickchart Scatterplot", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract overall ratings and distribution percentages": { - "main": [ - [ - { - "node": "Define contributions to variance", - "type": "main", - "index": 0 - } - ] - ] - } - } -} \ No newline at end of file diff --git a/workflows/dYjQS1bJmVSAxNnj_BambooHR_AI-Powered_Company_Policies_and_Benefits_Chatbot.json b/workflows/dYjQS1bJmVSAxNnj_BambooHR_AI-Powered_Company_Policies_and_Benefits_Chatbot.json deleted file mode 100644 index f8d7fba..0000000 --- a/workflows/dYjQS1bJmVSAxNnj_BambooHR_AI-Powered_Company_Policies_and_Benefits_Chatbot.json +++ /dev/null @@ -1,1383 +0,0 @@ -{ - "id": "dYjQS1bJmVSAxNnj", - "meta": { - "instanceId": "a9f3b18652ddc96459b459de4fa8fa33252fb820a9e5a1593074f3580352864a", - "templateCredsSetupCompleted": true - }, - "name": "BambooHR AI-Powered Company Policies and Benefits Chatbot", - "tags": [], - "nodes": [ - { - "id": "832e4a1d-320f-4793-be3c-8829776a3ce6", - "name": "When clicking β€˜Test workflow’", - "type": "n8n-nodes-base.manualTrigger", - "position": [ - 760, - 560 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "63be0638-d7df-4af8-ba56-555593a6de0c", - "name": "Default Data Loader", - "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader", - "position": [ - 2080, - 740 - ], - "parameters": { - "options": {}, - "dataType": "binary" - }, - "typeVersion": 1 - }, - { - "id": "ffe33bb2-efd0-4b6e-a146-aaded7c28304", - "name": "Embeddings OpenAI", - "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", - "position": [ - 1860, - 740 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1.1 - }, - { - "id": "32de5318-ea5d-4951-b81c-3c96167bc320", - "name": "Recursive Character Text Splitter", - "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter", - "position": [ - 2060, - 880 - ], - "parameters": { - "options": {}, - "chunkOverlap": 100 - }, - "typeVersion": 1 - }, - { - "id": "6306d263-16c1-4a68-9318-c58fea1e3e62", - "name": "Window Buffer Memory", - "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow", - "position": [ - 1000, - 1340 - ], - "parameters": {}, - "typeVersion": 1.2 - }, - { - "id": "364cf0ce-524c-4b61-89f3-40b2801bc7e3", - "name": "OpenAI Chat Model", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 840, - 1340 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "901163a1-1e66-42ee-bfd0-9ed815a7c83d", - "name": "Vector Store Tool", - "type": "@n8n/n8n-nodes-langchain.toolVectorStore", - "position": [ - 1120, - 1380 - ], - "parameters": { - "name": "company_files", - "topK": 5, - "description": "Retrieves information from the company handbook, 401k policies, benefits overview, and expense policies available to all employees." - }, - "typeVersion": 1 - }, - { - "id": "b87fa113-6a32-48fc-8e06-049345c66f38", - "name": "OpenAI Chat Model1", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 1220, - 1600 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "9dc1a896-c8a5-4d22-b029-14eae0717bd8", - "name": "Embeddings OpenAI1", - "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi", - "position": [ - 940, - 1700 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1.1 - }, - { - "id": "20cda474-ef6f-48af-b299-04f1fe980d3d", - "name": "Employee Lookup Tool", - "type": "@n8n/n8n-nodes-langchain.toolWorkflow", - "position": [ - 1440, - 1360 - ], - "parameters": { - "name": "employee_lookup_tool", - "workflowId": { - "__rl": true, - "mode": "id", - "value": "={{ $workflow.id }}" - }, - "description": "Call this tool with the full name of an employee to retrieve their details from our HRIS, including their job title, department, and supervisor. If an employee name is not provided, you may call this tool with a department name to retrieve the most senior person in that department. This tool requires an exact match on employee names but can infer the senior-most person for a department query.", - "jsonSchemaExample": "{\n\t\"name\": \"The name of an employee or department\"\n}", - "specifyInputSchema": true - }, - "typeVersion": 1.2 - }, - { - "id": "55718295-459b-4a4b-8c57-fd6b31e3d963", - "name": "OpenAI Chat Model2", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 1960, - 1500 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "e574d63d-7e38-4d90-9533-64a4ddbe2e36", - "name": "OpenAI Chat Model3", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 2980, - 1600 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "04d53430-b8d9-43ff-b2c4-ef0da2d799c0", - "name": "OpenAI Chat Model4", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 3700, - 1620 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "9759fe08-3c81-4472-8d62-2c5d26156984", - "name": "Auto-fixing Output Parser", - "type": "@n8n/n8n-nodes-langchain.outputParserAutofixing", - "position": [ - 3880, - 1600 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "d8830fd8-f238-4e5d-8c5f-bf83c9450dbe", - "name": "OpenAI Chat Model5", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 3780, - 1700 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "da580308-e4ed-400b-99e2-31baf27b039d", - "name": "Structured Output Parser", - "type": "@n8n/n8n-nodes-langchain.outputParserStructured", - "position": [ - 4080, - 1700 - ], - "parameters": { - "jsonSchemaExample": "{\n\t\"name\": \"The name of an employee\"\n}" - }, - "typeVersion": 1.2 - }, - { - "id": "e81dbe81-5f6b-4b2c-a4bc-afa0136e33ac", - "name": "Sticky Note", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 680, - 460 - ], - "parameters": { - "color": 7, - "width": 1695.17727595829, - "height": 582.7965199011514, - "content": "## STEP #1: Retrieve company policies and load them into a vector store" - }, - "typeVersion": 1 - }, - { - "id": "629872ed-2f99-424d-96da-feee6df96d3d", - "name": "Sticky Note1", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 680, - 1080 - ], - "parameters": { - "color": 4, - "width": 873.5637402697844, - "height": 780.6181567295652, - "content": "## BambooHR AI-Powered HR Benefits and Company Policies Chatbot" - }, - "typeVersion": 1 - }, - { - "id": "8888281b-5701-4c62-b76b-a0b6a80d8463", - "name": "Sticky Note2", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1580, - 1075.4375994898523 - ], - "parameters": { - "color": 7, - "width": 2783.3549952823255, - "height": 781.525845027296, - "content": "## (Optional) STEP #2: Set up employee lookup tool" - }, - "typeVersion": 1 - }, - { - "id": "17044553-d081-4c17-8108-d0327709f352", - "name": "GET all files", - "type": "n8n-nodes-base.bambooHr", - "position": [ - 960, - 560 - ], - "parameters": { - "resource": "file", - "operation": "getAll", - "returnAll": true, - "simplifyOutput": false - }, - "credentials": { - "bambooHrApi": { - "id": "XXXXXX", - "name": "BambooHR account" - } - }, - "typeVersion": 1 - }, - { - "id": "939881b1-eb18-4ab7-ac4a-9edcc218356f", - "name": "Sticky Note3", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 920, - 720 - ], - "parameters": { - "color": 5, - "width": 177.89252000024067, - "height": 99.24268260893132, - "content": "Toggle **off** the _simplify_ option to ensure categories are retrieved as well" - }, - "typeVersion": 1 - }, - { - "id": "0907a1d3-97e2-4219-bfbc-524186f6d889", - "name": "Filter out files from undesired categories", - "type": "n8n-nodes-base.filter", - "position": [ - 1160, - 560 - ], - "parameters": { - "options": {}, - "conditions": { - "options": { - "version": 2, - "leftValue": "", - "caseSensitive": true, - "typeValidation": "strict" - }, - "combinator": "and", - "conditions": [ - { - "id": "b85b86cd-0b54-4348-a538-8ff4ae625b9a", - "operator": { - "name": "filter.operator.equals", - "type": "string", - "operation": "equals" - }, - "leftValue": "={{ $json.name }}", - "rightValue": "=Company Files" - } - ] - } - }, - "typeVersion": 2.2 - }, - { - "id": "43069219-7cd9-4515-846d-ed6a0f9bbb61", - "name": "Split out individual files", - "type": "n8n-nodes-base.splitOut", - "position": [ - 1360, - 560 - ], - "parameters": { - "options": {}, - "fieldToSplitOut": "files" - }, - "typeVersion": 1 - }, - { - "id": "8412af5f-f07f-4a98-a174-e363ba04f902", - "name": "Filter out non-pdf files", - "type": "n8n-nodes-base.filter", - "position": [ - 1560, - 560 - ], - "parameters": { - "options": {}, - "conditions": { - "options": { - "version": 2, - "leftValue": "", - "caseSensitive": true, - "typeValidation": "strict" - }, - "combinator": "and", - "conditions": [ - { - "id": "73cc2cb9-04fa-43e7-a459-de0bf26ffb18", - "operator": { - "type": "boolean", - "operation": "true", - "singleValue": true - }, - "leftValue": "={{ $json.originalFileName.endsWith(\".pdf\") }}", - "rightValue": "" - } - ] - } - }, - "typeVersion": 2.2 - }, - { - "id": "7e007a29-c902-41d3-ab22-f6a93bc43f7d", - "name": "Download file from BambooHR", - "type": "n8n-nodes-base.bambooHr", - "position": [ - 1760, - 560 - ], - "parameters": { - "fileId": "={{ $json.id }}", - "resource": "file", - "operation": "download" - }, - "credentials": { - "bambooHrApi": { - "id": "XXXXXX", - "name": "BambooHR account" - } - }, - "typeVersion": 1 - }, - { - "id": "cec7ce3a-77df-4400-8683-fb5cf87004b6", - "name": "Supabase Vector Store", - "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase", - "position": [ - 1960, - 560 - ], - "parameters": { - "mode": "insert", - "options": { - "queryName": "match_files" - }, - "tableName": { - "__rl": true, - "mode": "list", - "value": "company_files", - "cachedResultName": "company_files" - } - }, - "credentials": { - "supabaseApi": { - "id": "XXXXXX", - "name": "Supabase account" - } - }, - "typeVersion": 1 - }, - { - "id": "5e070dc3-5f6d-44bb-a655-b769aac14890", - "name": "Sticky Note4", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1600, - 1140 - ], - "parameters": { - "color": 5, - "width": 530.9221622705562, - "height": 91.00370621080086, - "content": "This employee lookup tool gives the AI Benefits and Company Policies chatbot additional superpowers by allowing it to **search for an individual or a department to retrieve contact information from BambooHR**." - }, - "typeVersion": 1 - }, - { - "id": "8f3cd44e-d1e5-4806-9d89-78c8728ea0e4", - "name": "Employee initiates a conversation", - "type": "@n8n/n8n-nodes-langchain.chatTrigger", - "position": [ - 760, - 1140 - ], - "webhookId": "27ec9df7-5007-4642-81c7-7fcf7e834c43", - "parameters": { - "options": {} - }, - "typeVersion": 1.1 - }, - { - "id": "3d56dc6a-13e2-404b-ad38-6370b9610f61", - "name": "Supabase Vector Store Retrieval", - "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase", - "position": [ - 940, - 1540 - ], - "parameters": { - "options": { - "queryName": "match_files" - }, - "tableName": { - "__rl": true, - "mode": "list", - "value": "company_files", - "cachedResultName": "company_files" - } - }, - "credentials": { - "supabaseApi": { - "id": "XXXXXX", - "name": "Supabase account" - } - }, - "typeVersion": 1 - }, - { - "id": "1e6f5d4a-5897-42b7-bfcf-e69b7880b6c4", - "name": "Sticky Note5", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 680, - 1880 - ], - "parameters": { - "width": 865.771928038017, - "height": 281.07009330339326, - "content": "### AI Chatbot Operating Guidelines \n- When an employee asks for a contact person, first attempt to find the relevant contact in company_files. \n- If a contact person is found but their details (e.g., email or phone number) are missing, use the `employee_lookup_tool` to retrieve their contact details. \n- If no contact person is found: \n 1. Use the `employee_lookup_tool` with \"HR\" (or another relevant department) to retrieve the most senior person in that department. \n 2. If no senior contact is found, ask the employee for their name. \n 3. Use the `employee_lookup_tool` to retrieve their supervisor’s name. \n 4. Use the `employee_lookup_tool` to retrieve their supervisor’s details. \n 5. Provide the supervisor's contact information and recommend them as the best next point of contact. " - }, - "typeVersion": 1 - }, - { - "id": "ba8c82cb-4972-46cc-8594-dfe71149a41c", - "name": "AI-Powered HR Benefits and Company Policies Chatbot", - "type": "n8n-nodes-base.executeWorkflowTrigger", - "position": [ - 1640, - 1340 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "aaf611fd-1779-4826-8f9c-4e9a7a538af0", - "name": "Text Classifier", - "type": "@n8n/n8n-nodes-langchain.textClassifier", - "position": [ - 1840, - 1340 - ], - "parameters": { - "options": {}, - "inputText": "={{ $json.query.name }}", - "categories": { - "categories": [ - { - "category": "person", - "description": "This is the name of a person." - }, - { - "category": "department", - "description": "This is the name of a department within the company." - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "4a1e0d47-87f8-4301-9aee-2227003a40e6", - "name": "GET all employees", - "type": "n8n-nodes-base.bambooHr", - "position": [ - 2260, - 1240 - ], - "parameters": { - "operation": "getAll", - "returnAll": true - }, - "credentials": { - "bambooHrApi": { - "id": "XXXXXX", - "name": "BambooHR account" - } - }, - "typeVersion": 1 - }, - { - "id": "93e1017a-07c6-4b97-be90-659a91fdc065", - "name": "Filter out other employees", - "type": "n8n-nodes-base.filter", - "position": [ - 2460, - 1240 - ], - "parameters": { - "options": {}, - "conditions": { - "options": { - "version": 2, - "leftValue": "", - "caseSensitive": true, - "typeValidation": "strict" - }, - "combinator": "and", - "conditions": [ - { - "id": "e80c892e-21dc-4d6e-8ef6-c2ffaea6d43e", - "operator": { - "name": "filter.operator.equals", - "type": "string", - "operation": "equals" - }, - "leftValue": "={{ $json.displayName }}", - "rightValue": "={{ $('AI-Powered HR Benefits and Company Policies Chatbot').item.json.query.name }}" - } - ] - } - }, - "typeVersion": 2.2 - }, - { - "id": "c45eec9a-05ca-4b35-b595-42f2251a01ec", - "name": "Stringify employee record for response", - "type": "n8n-nodes-base.set", - "position": [ - 2660, - 1240 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "73ae7ef0-339a-4e32-bbc9-c40cefd37757", - "name": "response", - "type": "string", - "value": "={{ $json.toJsonString() }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "aa30062a-2476-4fc2-8380-6d2106885ae2", - "name": "GET all employees (second path)", - "type": "n8n-nodes-base.bambooHr", - "position": [ - 2260, - 1440 - ], - "parameters": { - "operation": "getAll", - "returnAll": true - }, - "credentials": { - "bambooHrApi": { - "id": "XXXXXX", - "name": "BambooHR account" - } - }, - "typeVersion": 1 - }, - { - "id": "f44cb9ab-00aa-4ebc-bb1a-6ba1da2e2aaa", - "name": "Extract departments", - "type": "n8n-nodes-base.aggregate", - "position": [ - 2460, - 1440 - ], - "parameters": { - "options": {}, - "fieldsToAggregate": { - "fieldToAggregate": [ - { - "renameField": true, - "outputFieldName": "departments", - "fieldToAggregate": "department" - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "855a6968-d919-4071-96d8-04cbc4b6ec39", - "name": "Ensure uniqueness in department list", - "type": "n8n-nodes-base.set", - "position": [ - 2660, - 1440 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "34f456ff-d2c5-431f-ade3-ace48abd0c6a", - "name": "departments", - "type": "array", - "value": "={{ $json.departments.unique() }}" - }, - { - "id": "cf31288a-65fc-45c6-8b6f-6680020dce09", - "name": "query", - "type": "string", - "value": "={{ $('Text Classifier').item.json.query.name }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "0dca5763-33c6-4444-b4e0-f26127bb91d5", - "name": "Extract department", - "type": "@n8n/n8n-nodes-langchain.informationExtractor", - "position": [ - 2860, - 1440 - ], - "parameters": { - "text": "={{ $json.query }}", - "options": {}, - "attributes": { - "attributes": [ - { - "name": "department", - "description": "=The department from the following list that would be most applicable:\n{{ $json.departments }}" - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "833b43e8-7ed5-4431-b362-b5d11bb9f787", - "name": "Retrieve all employees", - "type": "n8n-nodes-base.bambooHr", - "position": [ - 3220, - 1440 - ], - "parameters": { - "operation": "getAll", - "returnAll": true - }, - "credentials": { - "bambooHrApi": { - "id": "XXXXXX", - "name": "BambooHR account" - } - }, - "typeVersion": 1 - }, - { - "id": "adcaafb5-700f-4e93-a7f4-c393967fb4f0", - "name": "Filter out other departments", - "type": "n8n-nodes-base.filter", - "position": [ - 3420, - 1440 - ], - "parameters": { - "options": {}, - "conditions": { - "options": { - "version": 2, - "leftValue": "", - "caseSensitive": true, - "typeValidation": "strict" - }, - "combinator": "and", - "conditions": [ - { - "id": "a88bf53c-ecfd-49a7-8180-1e8b8eaeb6fd", - "operator": { - "name": "filter.operator.equals", - "type": "string", - "operation": "equals" - }, - "leftValue": "={{ $json.department }}", - "rightValue": "={{ $('Extract department').item.json.output.department }}" - } - ] - } - }, - "typeVersion": 2.2 - }, - { - "id": "fe928eb9-2b70-4ab9-a5a6-a4c141467ad7", - "name": "Extract relevant employee fields", - "type": "n8n-nodes-base.aggregate", - "position": [ - 3620, - 1440 - ], - "parameters": { - "include": "specifiedFields", - "options": {}, - "aggregate": "aggregateAllItemData", - "fieldsToInclude": "id, displayName, jobTitle, workEmail", - "destinationFieldName": "department_employees" - }, - "typeVersion": 1 - }, - { - "id": "0632ae1b-280e-486e-9cdd-c6c9fd2a1b6e", - "name": "Identify most senior employee", - "type": "@n8n/n8n-nodes-langchain.chainLlm", - "position": [ - 3800, - 1440 - ], - "parameters": { - "text": "=Who is the most senior employee from this list:\n{{ $json.department_employees.toJsonString() }}", - "promptType": "define", - "hasOutputParser": true - }, - "typeVersion": 1.4 - }, - { - "id": "0e6c8d0a-d84f-468b-993b-c5a14d7d458f", - "name": "Format name for response", - "type": "n8n-nodes-base.set", - "position": [ - 4160, - 1440 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "2b4412bf-142b-4ba0-a6b2-654e97c263e5", - "name": "response", - "type": "string", - "value": "={{ $json.output.name }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "e865d8bf-ab6d-4d23-9d7c-a76f96ba75a1", - "name": "HR AI Agent", - "type": "@n8n/n8n-nodes-langchain.agent", - "position": [ - 1040, - 1140 - ], - "parameters": { - "options": { - "systemMessage": "You are a helpful HR assistant accessible by employees at our company.\n\nObjective: \nAssist employees with questions regarding company policies, documents, and escalation procedures.\n\nTools: \n1. A vector store database (company_files) containing the company handbook, 401k policy, expense policy, and employee benefits. \n2. An employee lookup tool (employee_lookup_tool) that retrieves details about an employee when provided with their name. It can also retrieve the most senior person in a department if given a department name. \n\nGuidelines: \n- When an employee asks for a contact person, first attempt to find the relevant contact in company_files. \n- If a contact person is found but their details (e.g., email or phone number) are missing, use the `employee_lookup_tool` to retrieve their contact details. \n- If no contact person is found: \n 1. Use the `employee_lookup_tool` with \"HR\" (or another relevant department) to retrieve the most senior person in that department. \n 2. If no senior contact is found, ask the employee for their name. \n 3. Use the `employee_lookup_tool` to retrieve their supervisor’s name. \n 4. Use the `employee_lookup_tool` to retrieve their supervisor’s details. \n 5. Provide the supervisor's contact information and recommend them as the best next point of contact. \n" - } - }, - "typeVersion": 1.7 - }, - { - "id": "3aa42dcf-a411-4bd8-87b3-9ab9d0043303", - "name": "Sticky Note6", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1600, - 1660 - ], - "parameters": { - "color": 3, - "width": 340.93489445096634, - "height": 180.79319430657273, - "content": "### GetAll employees from BambooHR\nBambooHR does not offer search by {field} functionality for its `/employees` endpoint, so filtering must be done after data retrieval. This can be inefficient for very large organizations where there may be multiple employees with the same name or simply a large number of employees." - }, - "typeVersion": 1 - }, - { - "id": "3b3b400c-9c7e-4fd0-91f3-1c6bcf05617f", - "name": "Sticky Note7", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2240, - 1140 - ], - "parameters": { - "color": 5, - "width": 542.9452105095002, - "height": 89.69037140899545, - "content": "### GET singular employee by name path\nThis path may be used multiple times by the HR AI Agent to look up the employee's details, and then to look up their supervisor's details." - }, - "typeVersion": 1 - }, - { - "id": "6ad78a36-e68d-4b0d-b532-ca67bcd0738d", - "name": "Sticky Note8", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2240, - 1620 - ], - "parameters": { - "color": 5, - "width": 542.9452105095002, - "height": 121.0648445295759, - "content": "### GET senior leader of department path\nThis path would normally only be used when no other contacts can be identified from the company_files. The employee can retrieve the contact details for the most senior leader of a department should they request it." - }, - "typeVersion": 1 - }, - { - "id": "25d1e603-cce0-4cd1-9293-810880c65584", - "name": "Sticky Note9", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 4020, - 1320 - ], - "parameters": { - "color": 5, - "width": 300.8019702746294, - "height": 97.8161667645835, - "content": "### Final node returns employee name\nThe AI Agent can then call the employee lookup path to retrieve details, if requested." - }, - "typeVersion": 1 - }, - { - "id": "e7076eaa-a67e-4b02-9aec-553c405f3bb9", - "name": "Sticky Note10", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 700, - 940 - ], - "parameters": { - "color": 4, - "width": 244.3952545193282, - "height": 87.34661077350344, - "content": "## About the maker\n**[Find Ludwig Gerdes on LinkedIn](https://www.linkedin.com/in/ludwiggerdes)**" - }, - "typeVersion": 1 - } - ], - "active": false, - "pinData": { - "AI-Powered HR Benefits and Company Policies Chatbot": [ - { - "json": { - "query": { - "name": "HR" - } - } - } - ] - }, - "settings": { - "executionOrder": "v1" - }, - "versionId": "b4306b84-994f-4cd0-b40c-33a234f75ef9", - "connections": { - "GET all files": { - "main": [ - [ - { - "node": "Filter out files from undesired categories", - "type": "main", - "index": 0 - } - ] - ] - }, - "Text Classifier": { - "main": [ - [ - { - "node": "GET all employees", - "type": "main", - "index": 0 - } - ], - [ - { - "node": "GET all employees (second path)", - "type": "main", - "index": 0 - } - ] - ] - }, - "Embeddings OpenAI": { - "ai_embedding": [ - [ - { - "node": "Supabase Vector Store", - "type": "ai_embedding", - "index": 0 - } - ] - ] - }, - "GET all employees": { - "main": [ - [ - { - "node": "Filter out other employees", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model": { - "ai_languageModel": [ - [ - { - "node": "HR AI Agent", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "Vector Store Tool": { - "ai_tool": [ - [ - { - "node": "HR AI Agent", - "type": "ai_tool", - "index": 0 - } - ] - ] - }, - "Embeddings OpenAI1": { - "ai_embedding": [ - [ - { - "node": "Supabase Vector Store Retrieval", - "type": "ai_embedding", - "index": 0 - } - ] - ] - }, - "Extract department": { - "main": [ - [ - { - "node": "Retrieve all employees", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model1": { - "ai_languageModel": [ - [ - { - "node": "Vector Store Tool", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model2": { - "ai_languageModel": [ - [ - { - "node": "Text Classifier", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model3": { - "ai_languageModel": [ - [ - { - "node": "Extract department", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model4": { - "ai_languageModel": [ - [ - { - "node": "Identify most senior employee", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model5": { - "ai_languageModel": [ - [ - { - "node": "Auto-fixing Output Parser", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "Default Data Loader": { - "ai_document": [ - [ - { - "node": "Supabase Vector Store", - "type": "ai_document", - "index": 0 - } - ] - ] - }, - "Extract departments": { - "main": [ - [ - { - "node": "Ensure uniqueness in department list", - "type": "main", - "index": 0 - } - ] - ] - }, - "Employee Lookup Tool": { - "ai_tool": [ - [ - { - "node": "HR AI Agent", - "type": "ai_tool", - "index": 0 - } - ] - ] - }, - "Window Buffer Memory": { - "ai_memory": [ - [ - { - "node": "HR AI Agent", - "type": "ai_memory", - "index": 0 - } - ] - ] - }, - "Retrieve all employees": { - "main": [ - [ - { - "node": "Filter out other departments", - "type": "main", - "index": 0 - } - ] - ] - }, - "Filter out non-pdf files": { - "main": [ - [ - { - "node": "Download file from BambooHR", - "type": "main", - "index": 0 - } - ] - ] - }, - "Structured Output Parser": { - "ai_outputParser": [ - [ - { - "node": "Auto-fixing Output Parser", - "type": "ai_outputParser", - "index": 0 - } - ] - ] - }, - "Auto-fixing Output Parser": { - "ai_outputParser": [ - [ - { - "node": "Identify most senior employee", - "type": "ai_outputParser", - "index": 0 - } - ] - ] - }, - "Filter out other employees": { - "main": [ - [ - { - "node": "Stringify employee record for response", - "type": "main", - "index": 0 - } - ] - ] - }, - "Split out individual files": { - "main": [ - [ - { - "node": "Filter out non-pdf files", - "type": "main", - "index": 0 - } - ] - ] - }, - "Download file from BambooHR": { - "main": [ - [ - { - "node": "Supabase Vector Store", - "type": "main", - "index": 0 - } - ] - ] - }, - "Filter out other departments": { - "main": [ - [ - { - "node": "Extract relevant employee fields", - "type": "main", - "index": 0 - } - ] - ] - }, - "Identify most senior employee": { - "main": [ - [ - { - "node": "Format name for response", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET all employees (second path)": { - "main": [ - [ - { - "node": "Extract departments", - "type": "main", - "index": 0 - } - ] - ] - }, - "Supabase Vector Store Retrieval": { - "ai_vectorStore": [ - [ - { - "node": "Vector Store Tool", - "type": "ai_vectorStore", - "index": 0 - } - ] - ] - }, - "Extract relevant employee fields": { - "main": [ - [ - { - "node": "Identify most senior employee", - "type": "main", - "index": 0 - } - ] - ] - }, - "Employee initiates a conversation": { - "main": [ - [ - { - "node": "HR AI Agent", - "type": "main", - "index": 0 - } - ] - ] - }, - "Recursive Character Text Splitter": { - "ai_textSplitter": [ - [ - { - "node": "Default Data Loader", - "type": "ai_textSplitter", - "index": 0 - } - ] - ] - }, - "When clicking β€˜Test workflow’": { - "main": [ - [ - { - "node": "GET all files", - "type": "main", - "index": 0 - } - ] - ] - }, - "Ensure uniqueness in department list": { - "main": [ - [ - { - "node": "Extract department", - "type": "main", - "index": 0 - } - ] - ] - }, - "Filter out files from undesired categories": { - "main": [ - [ - { - "node": "Split out individual files", - "type": "main", - "index": 0 - } - ] - ] - }, - "AI-Powered HR Benefits and Company Policies Chatbot": { - "main": [ - [ - { - "node": "Text Classifier", - "type": "main", - "index": 0 - } - ] - ] - } - } -} \ No newline at end of file diff --git a/workflows/sB6dC0GZ7zZHuMGF_Test_Webhooks_in_n8n_Without_Changing_WEBHOOK_URL_(PostBin_&_BambooHR_Example).json b/workflows/sB6dC0GZ7zZHuMGF_Test_Webhooks_in_n8n_Without_Changing_WEBHOOK_URL_(PostBin_&_BambooHR_Example).json deleted file mode 100644 index cff8d60..0000000 --- a/workflows/sB6dC0GZ7zZHuMGF_Test_Webhooks_in_n8n_Without_Changing_WEBHOOK_URL_(PostBin_&_BambooHR_Example).json +++ /dev/null @@ -1,1445 +0,0 @@ -{ - "id": "sB6dC0GZ7zZHuMGF", - "meta": { - "instanceId": "a9f3b18652ddc96459b459de4fa8fa33252fb820a9e5a1593074f3580352864a", - "templateCredsSetupCompleted": true - }, - "name": "Test Webhooks in n8n Without Changing WEBHOOK_URL (PostBin & BambooHR Example)", - "tags": [ - { - "id": "qtD3SYKEoYtiqguT", - "name": "building_blocks", - "createdAt": "2025-02-08T21:20:40.051Z", - "updatedAt": "2025-02-08T21:20:40.051Z" - }, - { - "id": "mCgqKYNfNWwqIQG3", - "name": "ai", - "createdAt": "2025-02-08T21:20:49.438Z", - "updatedAt": "2025-02-08T21:20:49.438Z" - }, - { - "id": "EjQkfx3v7nH79HWo", - "name": "hr", - "createdAt": "2025-02-08T21:20:57.598Z", - "updatedAt": "2025-02-08T21:20:57.598Z" - }, - { - "id": "suSDrJxibUi10zsu", - "name": "engineering", - "createdAt": "2025-02-08T21:21:43.564Z", - "updatedAt": "2025-02-08T21:21:43.564Z" - } - ], - "nodes": [ - { - "id": "2529ea94-8427-4fbb-bac0-79fec29fe943", - "name": "When clicking β€˜Test workflow’", - "type": "n8n-nodes-base.manualTrigger", - "position": [ - 440, - 1220 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "067ce1b6-a511-448b-a268-7d0869ed2b36", - "name": "Sticky Note", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 600, - 980 - ], - "parameters": { - "color": 6, - "width": 550.7128407259806, - "height": 151.03568930452542, - "content": "### Requirements:\n1. **BambooHR instance** ([free trial link](https://www.bamboohr.com/signup/))\n2. **BambooHR API key*** ([documentation](https://documentation.bamboohr.com/docs/getting-started#authentication))\n3. **Slack connection** ([n8n documentation](https://docs.n8n.io/integrations/builtin/credentials/slack/))\n* **Note about API key**: Set up in n8n as Generic Credential (Basic Auth) with the API key as the username and any string for the password.\n\n" - }, - "typeVersion": 1 - }, - { - "id": "62a65021-8bc5-4bd3-95e4-b0616c0cbbe6", - "name": "Sticky Note1", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1620, - 1620 - ], - "parameters": { - "color": 7, - "width": 804.2810233962304, - "height": 154.2786603126325, - "content": "## Other use cases for BambooHR webhook\n1. Fraud & Compliance Monitoring (Triggered by Pay Rate, Pay Type, Compensation Change Reason, Bonus Amount, Commission Amount)\n2. Offboarding & Security Access Revocation (Triggered by Employment Status, Job Title, Department, Location)\n3. Manager Change Alert for Team & Workflow Updates (Triggered by Reporting To, Job Title, Department)" - }, - "typeVersion": 1 - }, - { - "id": "63e5f28a-83ea-44be-ad91-ab2b635551a1", - "name": "Sticky Note2", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 800, - 1140 - ], - "parameters": { - "color": 7, - "width": 600.2141303561856, - "height": 246.1007234368067, - "content": "## Create a new Bin in PostBin (STEP #1 above)" - }, - "typeVersion": 1 - }, - { - "id": "1afbac45-116e-4c8b-886c-24a96ba286ab", - "name": "Merge", - "type": "n8n-nodes-base.merge", - "position": [ - 1680, - 1240 - ], - "parameters": { - "mode": "combine", - "options": {}, - "combineBy": "combineByPosition" - }, - "typeVersion": 3 - }, - { - "id": "367315b0-eba5-4768-bdb0-8be23d965f6c", - "name": "Sticky Note3", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1840, - 1180 - ], - "parameters": { - "color": 7, - "width": 424.9937286279833, - "height": 248.92215299422725, - "content": "## Register webhook (STEP #2 above)" - }, - "typeVersion": 1 - }, - { - "id": "5b860a4e-66c9-4996-bd8f-ac642eca9021", - "name": "Sticky Note4", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1400, - 300 - ], - "parameters": { - "color": 4, - "width": 291.16380512688715, - "height": 397.605174332017, - "content": "## STEP #3: Confirm webhook functionality" - }, - "typeVersion": 1 - }, - { - "id": "c6d78f60-0e05-452c-b50d-4bee9b4e1220", - "name": "Sticky Note5", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 600, - 300 - ], - "parameters": { - "color": 4, - "width": 611.7032537942721, - "height": 397.94343220191183, - "content": "## STEP #1: Create a new Bin in PostBin\nNo authentication needed. Use API to create Bin and retrieve BinId to craft URL for subsequent usage." - }, - "typeVersion": 1 - }, - { - "id": "6bdd564e-daf7-4259-a283-547f8257dcce", - "name": "Sticky Note6", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 580, - 140 - ], - "parameters": { - "color": 7, - "width": 1140.1894415469083, - "height": 593.490746966612, - "content": "## How to Test a Short-Lived Webhook in n8n **WITHOUT** Changing WEBHOOK_URL\nTypically in n8n, in order to test a webhook, you first need to go through the process of changing the [**WEBHOOK_URL**](https://docs.n8n.io/hosting/configuration/configuration-examples/webhook-url/) environment variable to an address that is accessible to the service you want to test. Time permitting, that can be done with [ngrok](https://ngrok.com/docs/getting-started/) ([example](https://docs.n8n.io/hosting/installation/server-setups/)) or by self-hosting with one of [n8n's recommended deployment options](https://docs.n8n.io/hosting/installation/server-setups/).\n\nBut if you're new to n8n and in a rush to test a webhook's functionality, you can use [PostBin](https://www.postb.in/) as demonstrated in this workflow to test a proof of concept fast and avoid any unnecessary time on n8n setup and configuration." - }, - "typeVersion": 1 - }, - { - "id": "06b12932-bc46-46ff-a316-518cd1e24546", - "name": "Sticky Note10", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1420, - 600 - ], - "parameters": { - "color": 2, - "width": 255.54164387152053, - "height": 80, - "content": "**This may respond with a 404**\nIf no requests have been sent to the Bin, an error is raised." - }, - "typeVersion": 1 - }, - { - "id": "17eabcf5-9ae7-4e79-bdb5-3664fa286aeb", - "name": "Create Bin", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 660, - 420 - ], - "parameters": { - "url": "https://www.postb.in/api/bin", - "method": "POST", - "options": {} - }, - "typeVersion": 4.2 - }, - { - "id": "5b233ff1-475a-48a7-a5d2-4ce82adb2213", - "name": "GET Bin", - "type": "n8n-nodes-base.postBin", - "position": [ - 860, - 420 - ], - "parameters": { - "binId": "={{ $json.binId }}", - "operation": "get", - "requestOptions": {} - }, - "typeVersion": 1 - }, - { - "id": "14e0b2fc-f1bb-4eae-be81-069641f27b53", - "name": "Sticky Note11", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 620, - 600 - ], - "parameters": { - "color": 7, - "width": 182.23771342026427, - "height": 80, - "content": "Uses API call to bypass broken PostBin create bin endpoint in n8n." - }, - "typeVersion": 1 - }, - { - "id": "2eb51697-744e-4bfc-ae3e-ad28bcdc21b1", - "name": "Sticky Note12", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 840, - 600 - ], - "parameters": { - "color": 7, - "width": 351.0986223154297, - "height": 80, - "content": "Retrieve the binId (can also be found in response of Create Bin node). Craft a url that uses `https://www.postb.in/:binId` structure" - }, - "typeVersion": 1 - }, - { - "id": "ae7367be-ca86-4cac-a763-3627a176d988", - "name": "Sticky Note7", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 580, - 740 - ], - "parameters": { - "width": 631.0482952232512, - "height": 113.5322633928848, - "content": "**Per PostBin API Documentation:**\nYou can hit the https://www.postb.in/:binId endpoint to collect any kind of request data whether it is a GET, POST, PUT, PATCH, DELETE or whatever. This particular endpoint is not RESTful and is not part of this API. It isn't RESTful by definition. ie. it is meant to collect whatever you send to it." - }, - "typeVersion": 1 - }, - { - "id": "be327737-1e33-4107-9f98-66a6d66d2886", - "name": "Format url for webhook", - "type": "n8n-nodes-base.set", - "position": [ - 1060, - 420 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "5235b8f1-f284-472f-b6a5-25c16bc4a66e", - "name": "webhook_url", - "type": "string", - "value": "=https://www.postb.in/{{ $json.binId }}" - }, - { - "id": "35d56f07-4f6b-422a-8a03-0c3e49f4d734", - "name": "binId", - "type": "string", - "value": "={{ $json.binId }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "463d247c-ac97-4d79-a0c9-8c0785240a73", - "name": "GET most recent request", - "type": "n8n-nodes-base.postBin", - "position": [ - 1500, - 420 - ], - "parameters": { - "binId": "={{ $('Format url for webhook').item.json.binId }}", - "resource": "request", - "operation": "removeFirst", - "requestOptions": {} - }, - "typeVersion": 1 - }, - { - "id": "ef07fa4e-1411-474e-ba98-171abae9542d", - "name": "MOCK request", - "type": "n8n-nodes-base.postBin", - "position": [ - 1260, - 580 - ], - "parameters": { - "binId": "={{ $('Format url for webhook').item.json.binId }}", - "resource": "request", - "operation": "send", - "binContent": "=", - "requestOptions": {} - }, - "typeVersion": 1 - }, - { - "id": "6769b161-6dff-4732-b1cd-900b2e64ffc9", - "name": "Sticky Note9", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 580, - 900 - ], - "parameters": { - "color": 4, - "width": 4124.530158203355, - "height": 962.561104644939, - "content": "## Example: Register and test a webhook in BambooHR\n### Scenario: Send a notification to Slack when new employees join the company" - }, - "typeVersion": 1 - }, - { - "id": "a7f57c0a-3918-450b-b1a7-edd80e6edcf6", - "name": "Create Bin1", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 860, - 1220 - ], - "parameters": { - "url": "https://www.postb.in/api/bin", - "method": "POST", - "options": {} - }, - "typeVersion": 4.2 - }, - { - "id": "8a9ef96b-eb99-4fe5-aa82-0b4453d90dff", - "name": "GET Bin1", - "type": "n8n-nodes-base.postBin", - "position": [ - 1060, - 1220 - ], - "parameters": { - "binId": "={{ $json.binId }}", - "operation": "get", - "requestOptions": {} - }, - "typeVersion": 1 - }, - { - "id": "c70ff70f-80c6-4516-b278-bad82655d78c", - "name": "Format url for webhook1", - "type": "n8n-nodes-base.set", - "position": [ - 1260, - 1220 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "5235b8f1-f284-472f-b6a5-25c16bc4a66e", - "name": "url", - "type": "string", - "value": "=https://www.postb.in/{{ $json.binId }}" - }, - { - "id": "35d56f07-4f6b-422a-8a03-0c3e49f4d734", - "name": "binId", - "type": "string", - "value": "={{ $json.binId }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "793cd3ab-1459-4382-b9f7-5630869a871e", - "name": "SET BambooHR subdomain", - "type": "n8n-nodes-base.set", - "position": [ - 660, - 1480 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "89c9eb04-196b-4cb0-afec-dab071dcc471", - "name": "subdomain", - "type": "string", - "value": "example" - } - ] - } - }, - "executeOnce": true, - "typeVersion": 3.4 - }, - { - "id": "06703339-8e5b-4267-ae23-15540ea00692", - "name": "Split out fields", - "type": "n8n-nodes-base.splitOut", - "position": [ - 1060, - 1480 - ], - "parameters": { - "options": {}, - "fieldToSplitOut": "fields" - }, - "typeVersion": 1 - }, - { - "id": "b8086b64-0e27-4294-a230-3d6f428a2ddb", - "name": "Combine fields to monitor", - "type": "n8n-nodes-base.aggregate", - "position": [ - 1460, - 1480 - ], - "parameters": { - "options": {}, - "fieldsToAggregate": { - "fieldToAggregate": [ - { - "renameField": true, - "outputFieldName": "monitorFields", - "fieldToAggregate": "alias" - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "6c75204f-8527-467f-b982-bed268843fde", - "name": "Format payload for BambooHR webhook", - "type": "n8n-nodes-base.set", - "position": [ - 1900, - 1240 - ], - "parameters": { - "include": "except", - "options": {}, - "assignments": { - "assignments": [ - { - "id": "188d1a10-d32c-4e48-8bad-f8a5002c34a9", - "name": "name", - "type": "string", - "value": "Webhook Test" - }, - { - "id": "cfcd6de9-c20f-4935-8b5f-548bd6c381bf", - "name": "format", - "type": "string", - "value": "json" - }, - { - "id": "c0b22bc7-d873-4973-9e27-6931dde4b8b1", - "name": "limit.times", - "type": "number", - "value": 1 - }, - { - "id": "5e912e0a-d3fe-46e5-b85a-b22be0ae3eb1", - "name": "limit.seconds", - "type": "number", - "value": 60 - }, - { - "id": "0a197fcf-4d30-4112-a441-5ee4dbfaa350", - "name": "postFields", - "type": "object", - "value": "={{ {\"employeeNumber\": \"Employee #\",\n \"firstName\": \"First name\",\n \"lastName\": \"Last name\",\n \"jobTitle\": \"Job title\"} }}" - }, - { - "id": "aa292476-0ee2-49fc-afce-4788ff37475a", - "name": "frequency", - "type": "object", - "value": "={\n \"hour\": null,\n \"minute\": null,\n \"day\": null,\n \"month\": null\n}" - }, - { - "id": "0e6c44e5-c918-4897-b865-5e1848ff8444", - "name": "subdomain", - "type": "string", - "value": "={{ $('SET BambooHR subdomain').first().json.subdomain }}" - } - ] - }, - "excludeFields": "binId", - "includeOtherFields": true - }, - "typeVersion": 3.4 - }, - { - "id": "b0191582-e8d3-4432-b8e8-38ff0fc782fb", - "name": "Create webhook in BambooHR", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 2100, - 1240 - ], - "parameters": { - "url": "=https://api.bamboohr.com/api/gateway.php/{{ $json.subdomain }}/v1/webhooks/", - "method": "POST", - "options": {}, - "jsonBody": "={{ $json.removeField(\"subdomain\").toJsonString() }}", - "sendBody": true, - "specifyBody": "json", - "authentication": "genericCredentialType", - "genericAuthType": "httpBasicAuth" - }, - "credentials": { - "httpBasicAuth": { - "id": "XXXXXX", - "name": "BambooHR Basic Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "6f8d47f3-1a80-4317-a9eb-89188c70618c", - "name": "Create dummy data for employees", - "type": "n8n-nodes-base.debugHelper", - "position": [ - 2380, - 1240 - ], - "parameters": { - "category": "randomData", - "randomDataCount": 3 - }, - "typeVersion": 1 - }, - { - "id": "b3ba2315-f7d7-474b-9f06-3dbad510fb93", - "name": "Sticky Note13", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 800, - 1407.2486467347771 - ], - "parameters": { - "color": 7, - "width": 794.510445997778, - "height": 368.01097806266364, - "content": "## GET fields from BambooHR to monitor for changes [[src]](https://documentation.bamboohr.com/reference/get-monitor-fields)" - }, - "typeVersion": 1 - }, - { - "id": "34956bf7-ef81-425b-a348-bffa99f278bd", - "name": "Sticky Note14", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2320, - 1180 - ], - "parameters": { - "color": 7, - "width": 416.47592441009544, - "height": 250.72353860519, - "content": "## Test webhook" - }, - "typeVersion": 1 - }, - { - "id": "077934b0-21c5-49ef-9482-fa52ecbe917f", - "name": "Keep only new employee fields", - "type": "n8n-nodes-base.filter", - "position": [ - 1260, - 1480 - ], - "parameters": { - "options": {}, - "conditions": { - "options": { - "version": 2, - "leftValue": "", - "caseSensitive": true, - "typeValidation": "strict" - }, - "combinator": "and", - "conditions": [ - { - "id": "e1daab1a-bee5-4308-82f9-6660e957722d", - "operator": { - "type": "array", - "operation": "contains", - "rightType": "any" - }, - "leftValue": "={{ [\"employmentHistoryStatus\",\"employeeStatusDate\",\"hireDate\",\"originalHireDate\"] }}", - "rightValue": "={{ $json.alias }}" - } - ] - } - }, - "typeVersion": 2.2 - }, - { - "id": "ecd27c9d-fe7a-45fa-b085-e68535c334af", - "name": "Sticky Note15", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 820, - 1653.074026323302 - ], - "parameters": { - "width": 568.1578343498747, - "height": 101.29440680672363, - "content": "### Note about this section\nDepending on your familiarity with BambooHR and your intention with the webhook, you could hard code the fields to monitor with your webhook or use AI to filter based on topic. I chose a middle ground for this example.\n" - }, - "typeVersion": 1 - }, - { - "id": "2b0ee3a5-1b9f-4f8f-b024-2c576573d2d6", - "name": "GET all possible fields to monitor in BambooHR", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 860, - 1480 - ], - "parameters": { - "url": "=https://api.bamboohr.com/api/gateway.php/{{ $json.subdomain }}/v1/webhooks/monitor_fields", - "options": {}, - "authentication": "genericCredentialType", - "genericAuthType": "httpBasicAuth" - }, - "credentials": { - "httpBasicAuth": { - "id": "XXXXXX", - "name": "BambooHR Basic Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "97923d51-c895-4215-b808-4ade22ea6011", - "name": "Register and test webhook", - "type": "n8n-nodes-base.noOp", - "position": [ - 1260, - 420 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "4e48efac-eec6-48cc-b940-b04bda667953", - "name": "Sticky Note8", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1228.9696450873366, - 300 - ], - "parameters": { - "color": 4, - "width": 157.46160832218783, - "height": 397.57230173351894, - "content": "## STEP #2\nUse the PostBin URL in place of your normal webhook" - }, - "typeVersion": 1 - }, - { - "id": "f7147f00-19d1-4c0f-a75b-a7fd18f16c31", - "name": "Sticky Note16", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2940, - 1040 - ], - "parameters": { - "color": 7, - "width": 296.68826711085643, - "height": 497.77627578351644, - "content": "## STEP #3: Confirm webhook functionality" - }, - "typeVersion": 1 - }, - { - "id": "ea428b8f-fb4c-44bd-bcf0-bb7f40f3ed98", - "name": "Check BambooHR for calls to webhook", - "type": "n8n-nodes-base.httpRequest", - "onError": "continueRegularOutput", - "position": [ - 3040, - 1140 - ], - "parameters": { - "url": "=https://api.bamboohr.com/api/gateway.php/{{ $('Format payload for BambooHR webhook').item.json.subdomain }}/v1/webhooks/{{ $('Create webhook in BambooHR').item.json.id }}/log", - "options": {}, - "authentication": "genericCredentialType", - "genericAuthType": "httpBasicAuth" - }, - "credentials": { - "httpBasicAuth": { - "id": "XXXXXX", - "name": "BambooHR Basic Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "2aa4610d-48a8-4c15-be21-1adbb3bb8b1a", - "name": "Create employee records with dummy data", - "type": "n8n-nodes-base.bambooHr", - "position": [ - 2580, - 1240 - ], - "parameters": { - "lastName": "={{ $json.lastname }}", - "firstName": "={{ $json.firstname }}", - "additionalFields": { - "hireDate": "={{ $now }}", - "department": 18264 - } - }, - "credentials": { - "bambooHrApi": { - "id": "XXXXXX", - "name": "BambooHR account" - } - }, - "typeVersion": 1 - }, - { - "id": "f912f38c-fb3b-4357-87fe-cca9aea7ebf4", - "name": "Split out employees", - "type": "n8n-nodes-base.splitOut", - "position": [ - 3300, - 1340 - ], - "parameters": { - "options": {}, - "fieldToSplitOut": "body.employees" - }, - "typeVersion": 1 - }, - { - "id": "200f8afe-f872-4598-b376-6e5cd053aa7d", - "name": "Format displayName", - "type": "n8n-nodes-base.set", - "position": [ - 3500, - 1340 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "41e8a654-af0e-42db-a9f8-23bc951d34a9", - "name": "displayName", - "type": "string", - "value": "={{ $json.fields[\"First name\"].value + \" \" + $json.fields[\"Last name\"].value}}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "5fdf5f56-42ea-4891-9b66-5d3d290d0862", - "name": "OpenAI Chat Model", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 4100, - 1480 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "c3b02b2a-2135-41da-a881-25cf2135ff71", - "name": "Auto-fixing Output Parser", - "type": "@n8n/n8n-nodes-langchain.outputParserAutofixing", - "position": [ - 4200, - 1480 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "e32e3977-1a4c-4b74-839e-278621ac59ec", - "name": "OpenAI Chat Model1", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 4200, - 1640 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "aaf59e1e-4db6-416b-8602-d5dab0959783", - "name": "Structured Output Parser", - "type": "@n8n/n8n-nodes-langchain.outputParserStructured", - "position": [ - 4420, - 1640 - ], - "parameters": { - "jsonSchemaExample": "{\n\t\"welcome_message\": \"We are excited to welcome employee_name to the company!\"\n}" - }, - "typeVersion": 1.2 - }, - { - "id": "cc6702aa-8e96-40ad-805e-306e94b0be13", - "name": "Basic LLM Chain", - "type": "@n8n/n8n-nodes-langchain.chainLlm", - "position": [ - 4100, - 1340 - ], - "parameters": { - "text": "=Write a message to be shared with other employees welcoming our new {{ $json.keys().first() + \": \" + $json.values().first().join(', ').replace(/ ([^,]*)$/, ' and $1') }} to the company.", - "promptType": "define", - "hasOutputParser": true - }, - "typeVersion": 1.4 - }, - { - "id": "7f2d7505-5554-4ea4-8bf9-1e05c56c2bc6", - "name": "Combine employees into list", - "type": "n8n-nodes-base.aggregate", - "position": [ - 3700, - 1340 - ], - "parameters": { - "options": {}, - "fieldsToAggregate": { - "fieldToAggregate": [ - { - "renameField": true, - "outputFieldName": "=employee", - "fieldToAggregate": "displayName" - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "b897a173-254f-445f-a3af-db9398d0c904", - "name": "Pluralize key", - "type": "n8n-nodes-base.renameKeys", - "position": [ - 3900, - 1340 - ], - "parameters": { - "keys": { - "key": [ - { - "newKey": "=employee{{ $if($json.employee.length > 1,\"s\",\"\") }}", - "currentKey": "employee" - } - ] - }, - "additionalOptions": {} - }, - "typeVersion": 1 - }, - { - "id": "7e0474f1-3a9a-4b30-91eb-0b0d107d8bd1", - "name": "Welcome employees on Slack", - "type": "n8n-nodes-base.slack", - "position": [ - 4480, - 1340 - ], - "webhookId": "700f2d63-f04a-4809-9602-75f3328b56f8", - "parameters": { - "text": "={{ $json.output.welcome_message }}", - "select": "channel", - "channelId": { - "__rl": true, - "mode": "list", - "value": "C08BWLDFS48", - "cachedResultName": "social" - }, - "otherOptions": {} - }, - "credentials": { - "slackApi": { - "id": "XXXXXX", - "name": "Slack account" - } - }, - "typeVersion": 2.2 - }, - { - "id": "99cd4b68-a789-4a78-9636-c26554d703ed", - "name": "Sticky Note17", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 3260, - 1240 - ], - "parameters": { - "color": 7, - "width": 1380.619460919744, - "height": 545.950640999295, - "content": "## (For example purposes) Send message to Slack channel welcoming new employees" - }, - "typeVersion": 1 - }, - { - "id": "37839a6d-b616-4e24-b24f-659064752360", - "name": "Sticky Note18", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 4340, - 920 - ], - "parameters": { - "color": 3, - "width": 342.10949704718837, - "height": 275.27825144542527, - "content": "## FOR TESTING: DELETE WEBHOOK" - }, - "typeVersion": 1 - }, - { - "id": "0e03ab51-dace-4aed-9f4e-16fbbb7f7173", - "name": "DELETE BambooHR webhook", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 4460, - 1020 - ], - "parameters": { - "url": "=https://api.bamboohr.com/api/gateway.php/{subdomain}/v1/webhooks/{webhook_id}", - "method": "DELETE", - "options": {}, - "authentication": "genericCredentialType", - "genericAuthType": "httpBasicAuth" - }, - "credentials": { - "httpBasicAuth": { - "id": "XXXXXX", - "name": "BambooHR Basic Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "81dc0021-3a7d-41f9-aef9-126143b51e9a", - "name": "Sticky Note20", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1840, - 1440 - ], - "parameters": { - "width": 424.0067532215409, - "height": 134.02025779064905, - "content": "BambooHR's `/webhook` API endpoint expects arguments passed in the body of the request. You can see what arguments are required in their [documentation](https://documentation.bamboohr.com/reference/post-webhook) and [examples](https://documentation.bamboohr.com/docs/webhook-api-permissioned). In the arguments we pass through, we have set our webhook to fire at the same frequency as BambooHR's rate limit: 1 time every 60 seconds." - }, - "typeVersion": 1 - }, - { - "id": "b4a246ff-200a-40bc-a79c-4f51b24e0948", - "name": "Sticky Note21", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2940, - 1557.4137607776859 - ], - "parameters": { - "width": 295.8585062958632, - "height": 227.09133367749476, - "content": "### What is this?\nIn the above two nodes, we performing two actions:\n\n1. Checking BambooHR for a record of calls made by it to the webhook URL we registered (provided by PostBin).\n2. Retrieving the most recent call made by BambooHR to the webhook URL from PostBin." - }, - "typeVersion": 1 - }, - { - "id": "b09041d0-42b7-4084-b336-5d9af288acf9", - "name": "GET most recent request1", - "type": "n8n-nodes-base.postBin", - "onError": "continueRegularOutput", - "position": [ - 3040, - 1340 - ], - "parameters": { - "binId": "={{ $('Merge').item.json.binId }}", - "resource": "request", - "operation": "removeFirst", - "requestOptions": {} - }, - "typeVersion": 1 - }, - { - "id": "ee2543e5-5fc6-48e1-a574-d351380df732", - "name": "Wait 60 + 1 seconds for webhook to fire", - "type": "n8n-nodes-base.wait", - "position": [ - 2780, - 1240 - ], - "webhookId": "61bbec81-dcf5-441e-b6dd-ad96b429e80d", - "parameters": { - "amount": 61 - }, - "executeOnce": true, - "typeVersion": 1.1 - }, - { - "id": "6f6a95ee-ec01-429c-8710-edc52b6cc185", - "name": "Sticky Note19", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1740, - 780 - ], - "parameters": { - "color": 5, - "width": 256.0973815349037, - "height": 87.34661077350344, - "content": "## About the maker\n**[Find Ludwig Gerdes on LinkedIn](https://www.linkedin.com/in/ludwiggerdes)**" - }, - "typeVersion": 1 - }, - { - "id": "fc8344ab-f643-4bc2-af97-a2022834b3c8", - "name": "Sticky Note22", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1740, - 520 - ], - "parameters": { - "color": 7, - "width": 255.71137685448693, - "height": 240.80136668021893, - "content": "![image](https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExdjM4dWFjeW1lNGVxc2Vsd2Z0aXB4cWNzZmN6aG41Y296cXVnem10eCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/5cL9WAVQREF3TkfhXj/giphy.gif#full-width)" - }, - "typeVersion": 1 - }, - { - "id": "58c5c5a6-2210-4506-9470-d6a55fae421a", - "name": "Sticky Note23", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 3280, - 1517.2043765224669 - ], - "parameters": { - "width": 410.05041971203013, - "height": 251.31245942384516, - "content": "## What's happening here?\nIn this section, we do the following:\n1. Extract employee information from webhook call (from PostBin)\n2. Create a displayName from each employee's first and last name\n3. Combine the names into a list and format the key\n4. Ask OpenAI to compose a welcome message with the employee names\n5. Post that welcome message to Slack" - }, - "typeVersion": 1 - } - ], - "active": false, - "pinData": {}, - "settings": { - "executionOrder": "v1" - }, - "versionId": "c8562d68-8706-4fe0-9983-b9ae6de379a0", - "connections": { - "Merge": { - "main": [ - [ - { - "node": "Format payload for BambooHR webhook", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET Bin": { - "main": [ - [ - { - "node": "Format url for webhook", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET Bin1": { - "main": [ - [ - { - "node": "Format url for webhook1", - "type": "main", - "index": 0 - } - ] - ] - }, - "Create Bin": { - "main": [ - [ - { - "node": "GET Bin", - "type": "main", - "index": 0 - } - ] - ] - }, - "Create Bin1": { - "main": [ - [ - { - "node": "GET Bin1", - "type": "main", - "index": 0 - } - ] - ] - }, - "Pluralize key": { - "main": [ - [ - { - "node": "Basic LLM Chain", - "type": "main", - "index": 0 - } - ] - ] - }, - "Basic LLM Chain": { - "main": [ - [ - { - "node": "Welcome employees on Slack", - "type": "main", - "index": 0 - } - ] - ] - }, - "Split out fields": { - "main": [ - [ - { - "node": "Keep only new employee fields", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model": { - "ai_languageModel": [ - [ - { - "node": "Basic LLM Chain", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "Format displayName": { - "main": [ - [ - { - "node": "Combine employees into list", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model1": { - "ai_languageModel": [ - [ - { - "node": "Auto-fixing Output Parser", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "Split out employees": { - "main": [ - [ - { - "node": "Format displayName", - "type": "main", - "index": 0 - } - ] - ] - }, - "Format url for webhook": { - "main": [ - [ - { - "node": "Register and test webhook", - "type": "main", - "index": 0 - } - ] - ] - }, - "SET BambooHR subdomain": { - "main": [ - [ - { - "node": "GET all possible fields to monitor in BambooHR", - "type": "main", - "index": 0 - } - ] - ] - }, - "Format url for webhook1": { - "main": [ - [ - { - "node": "Merge", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET most recent request1": { - "main": [ - [ - { - "node": "Split out employees", - "type": "main", - "index": 0 - } - ] - ] - }, - "Structured Output Parser": { - "ai_outputParser": [ - [ - { - "node": "Auto-fixing Output Parser", - "type": "ai_outputParser", - "index": 0 - } - ] - ] - }, - "Auto-fixing Output Parser": { - "ai_outputParser": [ - [ - { - "node": "Basic LLM Chain", - "type": "ai_outputParser", - "index": 0 - } - ] - ] - }, - "Combine fields to monitor": { - "main": [ - [ - { - "node": "Merge", - "type": "main", - "index": 1 - } - ] - ] - }, - "Register and test webhook": { - "main": [ - [ - { - "node": "GET most recent request", - "type": "main", - "index": 0 - } - ] - ] - }, - "Create webhook in BambooHR": { - "main": [ - [ - { - "node": "Create dummy data for employees", - "type": "main", - "index": 0 - } - ] - ] - }, - "Combine employees into list": { - "main": [ - [ - { - "node": "Pluralize key", - "type": "main", - "index": 0 - } - ] - ] - }, - "Keep only new employee fields": { - "main": [ - [ - { - "node": "Combine fields to monitor", - "type": "main", - "index": 0 - } - ] - ] - }, - "Create dummy data for employees": { - "main": [ - [ - { - "node": "Create employee records with dummy data", - "type": "main", - "index": 0 - } - ] - ] - }, - "When clicking β€˜Test workflow’": { - "main": [ - [ - { - "node": "Create Bin1", - "type": "main", - "index": 0 - }, - { - "node": "SET BambooHR subdomain", - "type": "main", - "index": 0 - } - ] - ] - }, - "Format payload for BambooHR webhook": { - "main": [ - [ - { - "node": "Create webhook in BambooHR", - "type": "main", - "index": 0 - } - ] - ] - }, - "Create employee records with dummy data": { - "main": [ - [ - { - "node": "Wait 60 + 1 seconds for webhook to fire", - "type": "main", - "index": 0 - } - ] - ] - }, - "Wait 60 + 1 seconds for webhook to fire": { - "main": [ - [ - { - "node": "Check BambooHR for calls to webhook", - "type": "main", - "index": 0 - }, - { - "node": "GET most recent request1", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET all possible fields to monitor in BambooHR": { - "main": [ - [ - { - "node": "Split out fields", - "type": "main", - "index": 0 - } - ] - ] - } - } -} \ No newline at end of file diff --git a/workflows/siXUnQhJpCJ9rHzu_Auto-Tag_Blog_Posts_in_WordPress_with_AI.json b/workflows/siXUnQhJpCJ9rHzu_Auto-Tag_Blog_Posts_in_WordPress_with_AI.json deleted file mode 100644 index 82e59f4..0000000 --- a/workflows/siXUnQhJpCJ9rHzu_Auto-Tag_Blog_Posts_in_WordPress_with_AI.json +++ /dev/null @@ -1,913 +0,0 @@ -{ - "id": "siXUnQhJpCJ9rHzu", - "meta": { - "instanceId": "a9f3b18652ddc96459b459de4fa8fa33252fb820a9e5a1593074f3580352864a", - "templateCredsSetupCompleted": true - }, - "name": "Auto-Tag Blog Posts in WordPress with AI", - "tags": [ - { - "id": "ijuVOmJpw5mCrzQX", - "name": "marketing", - "createdAt": "2025-01-28T16:42:03.029Z", - "updatedAt": "2025-01-28T16:42:03.029Z" - } - ], - "nodes": [ - { - "id": "0561d80b-f360-4a8e-930d-49b778833991", - "name": "OpenAI Chat Model", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 3260, - 480 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "yWpagxp5s8o3dlBp", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "d71aec64-299c-4258-8eb4-95821d15b758", - "name": "Auto-fixing Output Parser", - "type": "@n8n/n8n-nodes-langchain.outputParserAutofixing", - "position": [ - 3460, - 540 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "1468a001-ca7b-4726-ae31-02b28d78b07e", - "name": "OpenAI Chat Model1", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 3360, - 680 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "yWpagxp5s8o3dlBp", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "bb4221ad-94d7-4543-850f-87b83735d2a6", - "name": "Structured Output Parser", - "type": "@n8n/n8n-nodes-langchain.outputParserStructured", - "position": [ - 3560, - 760 - ], - "parameters": { - "jsonSchemaExample": "{\n\t\"tags\": [\"Germany\", \"Technology\", \"Workflow Automation\"]\n}" - }, - "typeVersion": 1.2 - }, - { - "id": "2380c4ea-d804-45b2-8341-417afa2ae21f", - "name": "RSS Feed Trigger", - "type": "n8n-nodes-base.rssFeedReadTrigger", - "position": [ - 3140, - 320 - ], - "parameters": { - "pollTimes": { - "item": [ - { - "mode": "everyMinute" - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "782e9c61-7d51-499b-89b2-888415c5116e", - "name": "Return article details", - "type": "n8n-nodes-base.set", - "position": [ - 4140, - 320 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "ebe28fc7-f166-4428-b3f3-b319f2d080df", - "name": "tag_ids", - "type": "array", - "value": "={{ $json.tag_ids }}" - }, - { - "id": "bc296683-2a93-42b4-a9a7-90a2bc22f37b", - "name": "title", - "type": "string", - "value": "={{ $('MOCK article').item.json.title }}" - }, - { - "id": "32dc0950-3708-447e-a3b6-a5c5ae9bdcd0", - "name": "content", - "type": "string", - "value": "={{ $('MOCK article').item.json.content }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "6b5ce61f-8351-40ab-9e63-51c3e85ce53d", - "name": "Split Out", - "type": "n8n-nodes-base.splitOut", - "position": [ - 2200, - 840 - ], - "parameters": { - "options": { - "destinationFieldName": "missing_tag" - }, - "fieldToSplitOut": "missing_tags" - }, - "typeVersion": 1 - }, - { - "id": "2338e3e8-cba4-48c8-8c1a-50019af70932", - "name": "Loop over articles", - "type": "n8n-nodes-base.splitInBatches", - "position": [ - 1980, - 320 - ], - "parameters": { - "options": {} - }, - "typeVersion": 3 - }, - { - "id": "39b89004-6032-4d22-8bcc-3dfd1d793ed0", - "name": "SET initial record", - "type": "n8n-nodes-base.set", - "position": [ - 2200, - 440 - ], - "parameters": { - "options": {}, - "includeOtherFields": true - }, - "typeVersion": 3.4 - }, - { - "id": "ec0b93cb-de9d-41be-9d4b-6846d3ee14a2", - "name": "GET WP tags", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 2440, - 440 - ], - "parameters": { - "url": "https://www.example.com/wp-json/wp/v2/tags", - "options": {}, - "authentication": "predefinedCredentialType", - "nodeCredentialType": "wordpressApi" - }, - "credentials": { - "wordpressApi": { - "id": "XXXXXXX", - "name": "Example" - } - }, - "executeOnce": true, - "typeVersion": 4.2, - "alwaysOutputData": true - }, - { - "id": "cbabadef-9f5f-4402-8bd7-255f5c237ff9", - "name": "POST WP tags", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 2420, - 840 - ], - "parameters": { - "url": "https://www.example.com/wp-json/wp/v2/tags", - "method": "POST", - "options": {}, - "sendQuery": true, - "authentication": "predefinedCredentialType", - "queryParameters": { - "parameters": [ - { - "name": "slug", - "value": "={{ $json.missing_tag }}" - }, - { - "name": "name", - "value": "={{ $json.missing_tag.replaceAll(\"-\",\" \").toTitleCase() }}" - } - ] - }, - "nodeCredentialType": "wordpressApi" - }, - "credentials": { - "wordpressApi": { - "id": "XXXXXXX", - "name": "Example" - } - }, - "executeOnce": false, - "typeVersion": 4.2 - }, - { - "id": "6bf40d39-4b42-413f-9502-3ca494f75bcb", - "name": "GET updated WP tags", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 2700, - 840 - ], - "parameters": { - "url": "https://www.example.com/wp-json/wp/v2/tags", - "options": {}, - "authentication": "predefinedCredentialType", - "nodeCredentialType": "wordpressApi" - }, - "credentials": { - "wordpressApi": { - "id": "XXXXXXX", - "name": "Example" - } - }, - "executeOnce": true, - "typeVersion": 4.2 - }, - { - "id": "aea9a631-0cd8-4ed8-9fb1-981b8e11f3dd", - "name": "Keep matches", - "type": "n8n-nodes-base.filter", - "position": [ - 2200, - 1040 - ], - "parameters": { - "options": {}, - "conditions": { - "options": { - "version": 2, - "leftValue": "", - "caseSensitive": true, - "typeValidation": "strict" - }, - "combinator": "and", - "conditions": [ - { - "id": "8ec4fdfc-73f3-4d7b-96e4-f42a18252599", - "operator": { - "type": "array", - "operation": "contains", - "rightType": "any" - }, - "leftValue": "={{ $('SET initial record').first().json.tags.map(item => item.toLowerCase().replaceAll(\" \",\"-\")) }}", - "rightValue": "={{ $json.slug }}" - } - ] - } - }, - "typeVersion": 2.2 - }, - { - "id": "6d71d7a5-495d-4809-b66f-9f1cba0d11c6", - "name": "Combine tag_ids", - "type": "n8n-nodes-base.aggregate", - "position": [ - 2420, - 1040 - ], - "parameters": { - "options": {}, - "fieldsToAggregate": { - "fieldToAggregate": [ - { - "renameField": true, - "outputFieldName": "tag_ids", - "fieldToAggregate": "id" - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "dc3cac68-dee8-4821-963b-b0594d1a7e0e", - "name": "Combine slugs", - "type": "n8n-nodes-base.aggregate", - "position": [ - 2700, - 440 - ], - "parameters": { - "options": {}, - "fieldsToAggregate": { - "fieldToAggregate": [ - { - "renameField": true, - "outputFieldName": "tags", - "fieldToAggregate": "slug" - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "8e0f668c-e3ac-4d70-9ffb-5515e6221c62", - "name": "If", - "type": "n8n-nodes-base.if", - "position": [ - 2440, - 640 - ], - "parameters": { - "options": {}, - "conditions": { - "options": { - "version": 2, - "leftValue": "", - "caseSensitive": true, - "typeValidation": "strict" - }, - "combinator": "and", - "conditions": [ - { - "id": "8d77d072-cb47-4fbb-831a-0e6f3ecefc71", - "operator": { - "type": "array", - "operation": "empty", - "singleValue": true - }, - "leftValue": "={{ $json.missing_tags }}", - "rightValue": "" - } - ] - } - }, - "typeVersion": 2.2 - }, - { - "id": "7988188d-07e6-4a36-94f2-e21d7677802e", - "name": "MOCK article", - "type": "n8n-nodes-base.set", - "position": [ - 3740, - 320 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "4a69cf1b-341a-40bc-a36a-b76c05bdd819", - "name": "title", - "type": "string", - "value": "={{ $('RSS Feed Trigger').item.json.title }}" - }, - { - "id": "63097eb0-6165-4365-a5b5-e9f3de65d715", - "name": "content", - "type": "string", - "value": "={{ $('RSS Feed Trigger').item.json.content }}" - }, - { - "id": "ae4859ec-ad14-403e-b5b6-53703fefe3f3", - "name": "categories", - "type": "array", - "value": "={{ $('RSS Feed Trigger').item.json.categories }}" - }, - { - "id": "3f94d5ac-5196-4ad0-acea-79c07b0ee2c6", - "name": "tags", - "type": "array", - "value": "={{ $json.output.tags }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "4578cb14-dc86-4bc4-8d59-f0c088574164", - "name": "Return missing tags", - "type": "n8n-nodes-base.code", - "position": [ - 2200, - 640 - ], - "parameters": { - "jsCode": "const new_ary = $('SET initial record').first().json.tags.map(x => x.toLowerCase().replaceAll(\" \",\"-\")).filter(x => !$input.first().json.tags.includes(x))\n\nreturn {\"missing_tags\": new_ary};" - }, - "typeVersion": 2 - }, - { - "id": "91c8dde5-58ce-4bf6-ac3c-0062cbf0046e", - "name": "Wordpress", - "type": "n8n-nodes-base.wordpress", - "position": [ - 4360, - 320 - ], - "parameters": { - "title": "=Demo tagging post: {{ $json.title }}", - "additionalFields": { - "tags": "={{ $json.tag_ids }}", - "content": "=This is a post to demo automatic tagging a WordPress postvia n8n. The following content could be rewritten in full or part with commentary using AI.\n\n{{ $json.content }}" - } - }, - "credentials": { - "wordpressApi": { - "id": "XXXXXXX", - "name": "Example" - } - }, - "typeVersion": 1 - }, - { - "id": "8257534e-f433-4225-a795-230fd367cc01", - "name": "Sticky Note1", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 3000, - 200 - ], - "parameters": { - "color": 7, - "width": 1673.0029952487134, - "height": 1061.6563737812796, - "content": "## Demo Usage in Another Workflow (Tagging an article discovered with an RSS feed)" - }, - "typeVersion": 1 - }, - { - "id": "b14e6fda-c569-4ada-90d9-77b61049c531", - "name": "Sticky Note2", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1680, - 198.96245932022566 - ], - "parameters": { - "color": 7, - "width": 1243.102096674096, - "height": 1077.24135750937, - "content": "## Auto-Tag Posts in WordPress\n\nThis workflow allows you to hand off the responsibility of tagging content for WordPress to an AI Agent in n8n with no data entry required." - }, - "typeVersion": 1 - }, - { - "id": "21420d0f-a5c9-4eac-b6d9-06d3a6de5fb9", - "name": "Demo Usage in Another Workflow", - "type": "n8n-nodes-base.executeWorkflowTrigger", - "position": [ - 1780, - 320 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "7571b196-3827-478f-b032-84d99adf4aa8", - "name": "Auto-Tag Posts in WordPress", - "type": "n8n-nodes-base.executeWorkflow", - "position": [ - 3940, - 320 - ], - "parameters": { - "mode": "each", - "options": {}, - "workflowId": { - "__rl": true, - "mode": "id", - "value": "siXUnQhJpCJ9rHzu" - } - }, - "typeVersion": 1.1 - }, - { - "id": "e5b63f63-09a6-452d-9d26-8501fc49d7fe", - "name": "Sticky Note", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2640, - 140 - ], - "parameters": { - "color": 5, - "width": 256.62869115182394, - "height": 146.4958582739091, - "content": "## Copy this workflow\n\nYou can use it inline by removing the Called by Another Workflow trigger, or as-is as a subworkflow" - }, - "typeVersion": 1 - }, - { - "id": "2ea9fbdd-b492-4030-b640-227a163d70ef", - "name": "Sticky Note3", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 3040, - 980 - ], - "parameters": { - "width": 409.8780943583022, - "height": 248.2919292392927, - "content": "Handing off tagging and categorization fully to AI lets you **put your WordPress account on autopilot** without a human-in-the-loop.\n\nIn this example the application is use-case agnostic, but with this workflow you can:\n1. Use AI to rewrite content with original thoughts and tags\n2. Ensure healthy information architecture on your site\n3. Quickly generate multivariate tag and category combinations for optimal SEO" - }, - "typeVersion": 1 - }, - { - "id": "57cfa462-fc71-4173-b7c9-8253c4e240d1", - "name": "Sticky Note4", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 3900, - 500 - ], - "parameters": { - "color": 3, - "width": 369.61896876326364, - "height": 103.91486928512641, - "content": "### To ensure data can be passed to subsequent nodes, make sure to select \"Run Once for Each Item\" if executing a subworkflow" - }, - "typeVersion": 1 - }, - { - "id": "7f1dfade-07be-49b7-b5ee-99b58f1e6cc7", - "name": "Sticky Note5", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2640, - 660 - ], - "parameters": { - "color": 6, - "width": 211.8330719827787, - "content": "## What's this? \nIf there are missing tags we create them in WP, otherwise we keep get them all from WP and keep the relevant ones." - }, - "typeVersion": 1 - }, - { - "id": "61711c71-3e45-4b06-80a8-b651177b585d", - "name": "Sticky Note6", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1960, - 540 - ], - "parameters": { - "color": 3, - "width": 174.33565557367925, - "height": 251.80401948434695, - "content": "## What's this? \nOne of the few potential failure points in this workflow, when checking for missing tags it's important that both the generated tags and the existing tags are in the same case (snake, dash, title)." - }, - "typeVersion": 1 - }, - { - "id": "31db85c9-e4c2-4409-9d92-7eb005223de0", - "name": "Generate tags for article", - "type": "@n8n/n8n-nodes-langchain.chainLlm", - "position": [ - 3360, - 320 - ], - "parameters": { - "text": "=Please provide 3-5 suitable tags for the following article:\n\n{{ $json.content }}\n\nTag Formatting Rules:\n1. Tags should be in title case", - "promptType": "define", - "hasOutputParser": true - }, - "typeVersion": 1.4 - }, - { - "id": "7d6eac92-6f6f-44a4-8dce-0830440a9dff", - "name": "Sticky Note7", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 1600, - 1040 - ], - "parameters": { - "width": 285.2555025627061, - "content": "## ! A note about cases !\nIf you want your tags to follow a different case than I am using (dash case for slug, title case for name), then you will need to update a few nodes in this workflow." - }, - "typeVersion": 1 - }, - { - "id": "133be2f7-071b-4651-b3b5-8052a64b7f49", - "name": "Sticky Note8", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2600, - 1200 - ], - "parameters": { - "color": 5, - "width": 296.01271681531176, - "content": "## Ready for a challenge?\n\nMake this subworkflow executable for both categories and tags, accounting for different API calls to different endpoints." - }, - "typeVersion": 1 - }, - { - "id": "7807e967-ac3d-4a4d-bd9d-f123d57e1676", - "name": "Sticky Note9", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 4400, - 1155.7364351382535 - ], - "parameters": { - "color": 4, - "width": 244.3952545193282, - "height": 87.34661077350344, - "content": "## About the maker\n**[Find Ludwig Gerdes on LinkedIn](https://www.linkedin.com/in/ludwiggerdes)**" - }, - "typeVersion": 1 - } - ], - "active": false, - "pinData": { - "Generate tags for article": [ - { - "json": { - "output": { - "tags": [ - "Team Achievements", - "Global Community", - "Product Growth", - "2024 Highlights", - "Reflecting on Progress" - ] - } - } - } - ] - }, - "settings": { - "executionOrder": "v1" - }, - "versionId": "3acdf19c-288e-4a3b-87ae-5adbf44285fe", - "connections": { - "If": { - "main": [ - [ - { - "node": "GET updated WP tags", - "type": "main", - "index": 0 - } - ], - [ - { - "node": "Split Out", - "type": "main", - "index": 0 - } - ] - ] - }, - "Split Out": { - "main": [ - [ - { - "node": "POST WP tags", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET WP tags": { - "main": [ - [ - { - "node": "Combine slugs", - "type": "main", - "index": 0 - } - ] - ] - }, - "Keep matches": { - "main": [ - [ - { - "node": "Combine tag_ids", - "type": "main", - "index": 0 - } - ] - ] - }, - "MOCK article": { - "main": [ - [ - { - "node": "Auto-Tag Posts in WordPress", - "type": "main", - "index": 0 - } - ] - ] - }, - "POST WP tags": { - "main": [ - [ - { - "node": "GET updated WP tags", - "type": "main", - "index": 0 - } - ] - ] - }, - "Combine slugs": { - "main": [ - [ - { - "node": "Return missing tags", - "type": "main", - "index": 0 - } - ] - ] - }, - "Combine tag_ids": { - "main": [ - [ - { - "node": "Loop over articles", - "type": "main", - "index": 0 - } - ] - ] - }, - "RSS Feed Trigger": { - "main": [ - [ - { - "node": "Generate tags for article", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model": { - "ai_languageModel": [ - [ - { - "node": "Generate tags for article", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "Loop over articles": { - "main": [ - [], - [ - { - "node": "SET initial record", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model1": { - "ai_languageModel": [ - [ - { - "node": "Auto-fixing Output Parser", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "SET initial record": { - "main": [ - [ - { - "node": "GET WP tags", - "type": "main", - "index": 0 - } - ] - ] - }, - "GET updated WP tags": { - "main": [ - [ - { - "node": "Keep matches", - "type": "main", - "index": 0 - } - ] - ] - }, - "Return missing tags": { - "main": [ - [ - { - "node": "If", - "type": "main", - "index": 0 - } - ] - ] - }, - "Return article details": { - "main": [ - [ - { - "node": "Wordpress", - "type": "main", - "index": 0 - } - ] - ] - }, - "Structured Output Parser": { - "ai_outputParser": [ - [ - { - "node": "Auto-fixing Output Parser", - "type": "ai_outputParser", - "index": 0 - } - ] - ] - }, - "Auto-fixing Output Parser": { - "ai_outputParser": [ - [ - { - "node": "Generate tags for article", - "type": "ai_outputParser", - "index": 0 - } - ] - ] - }, - "Generate tags for article": { - "main": [ - [ - { - "node": "MOCK article", - "type": "main", - "index": 0 - } - ] - ] - }, - "Auto-Tag Posts in WordPress": { - "main": [ - [ - { - "node": "Return article details", - "type": "main", - "index": 0 - } - ] - ] - }, - "Demo Usage in Another Workflow": { - "main": [ - [ - { - "node": "Loop over articles", - "type": "main", - "index": 0 - } - ] - ] - } - } -} \ No newline at end of file diff --git a/workflows/vzU9QRZsHcyRsord_Spot_Workplace_Discrimination_Patterns_with_AI.json b/workflows/vzU9QRZsHcyRsord_Spot_Workplace_Discrimination_Patterns_with_AI.json deleted file mode 100644 index e30d918..0000000 --- a/workflows/vzU9QRZsHcyRsord_Spot_Workplace_Discrimination_Patterns_with_AI.json +++ /dev/null @@ -1,1850 +0,0 @@ -{ - "id": "vzU9QRZsHcyRsord", - "meta": { - "instanceId": "a9f3b18652ddc96459b459de4fa8fa33252fb820a9e5a1593074f3580352864a", - "templateCredsSetupCompleted": true - }, - "name": "Spot Workplace Discrimination Patterns with AI", - "tags": [ - { - "id": "76EYz9X3GU4PtgSS", - "name": "human_resources", - "createdAt": "2025-01-30T18:52:17.614Z", - "updatedAt": "2025-01-30T18:52:17.614Z" - }, - { - "id": "ey2Mx4vNaV8cKvao", - "name": "openai", - "createdAt": "2024-12-23T07:10:13.400Z", - "updatedAt": "2024-12-23T07:10:13.400Z" - } - ], - "nodes": [ - { - "id": "b508ab50-158a-4cbf-a52e-f53e1804e770", - "name": "When clicking β€˜Test workflow’", - "type": "n8n-nodes-base.manualTrigger", - "position": [ - 280, - 380 - ], - "parameters": {}, - "typeVersion": 1 - }, - { - "id": "11a1a2d5-a274-44f7-97ca-5666a59fcb31", - "name": "OpenAI Chat Model1", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 2220, - 800 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "395f7b67-c914-4aae-8727-0573fdbfc6ad", - "name": "OpenAI Chat Model2", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 2220, - 380 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "6ab194a9-b869-4296-aea9-19afcbffc0d7", - "name": "Merge", - "type": "n8n-nodes-base.merge", - "position": [ - 2940, - 600 - ], - "parameters": { - "mode": "combine", - "options": {}, - "combineBy": "combineByPosition" - }, - "typeVersion": 3 - }, - { - "id": "1eba1dd7-a164-4c70-8c75-759532bd16a0", - "name": "OpenAI Chat Model", - "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", - "position": [ - 3840, - 420 - ], - "parameters": { - "options": {} - }, - "credentials": { - "openAiApi": { - "id": "XXXXXX", - "name": "OpenAi account" - } - }, - "typeVersion": 1 - }, - { - "id": "f25f1b07-cded-4ca7-9655-8b8f463089ab", - "name": "SET company_name", - "type": "n8n-nodes-base.set", - "position": [ - 540, - 380 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "dd256ef7-013c-4769-8580-02c2d902d0b2", - "name": "company_name", - "type": "string", - "value": "=Twilio" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "87264a93-ab97-4e39-8d40-43365189f704", - "name": "Define dictionary of demographic keys", - "type": "n8n-nodes-base.set", - "position": [ - 740, - 380 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "6ae671be-45d0-4a94-a443-2f1d4772d31b", - "name": "asian", - "type": "string", - "value": "Asian" - }, - { - "id": "6c93370c-996c-44a6-a34c-4cd3baeeb846", - "name": "hispanic", - "type": "string", - "value": "Hispanic or Latinx" - }, - { - "id": "dee79039-6051-4e9d-98b5-63a07d30f6b0", - "name": "white", - "type": "string", - "value": "White" - }, - { - "id": "08d42380-8397-412f-8459-7553e9309b5d", - "name": "pacific_islander", - "type": "string", - "value": "Native Hawaiian or other Pacific Islander" - }, - { - "id": "09e8ebc5-e7e7-449a-9036-9b9b54cdc828", - "name": "black", - "type": "string", - "value": "Black or African American" - }, - { - "id": "39e910f8-3a8b-4233-a93a-3c5693e808c6", - "name": "middle_eastern", - "type": "string", - "value": "Middle Eastern" - }, - { - "id": "169b3471-efa0-476e-aa83-e3f717c568f1", - "name": "indigenous", - "type": "string", - "value": "Indigenous American or Native Alaskan" - }, - { - "id": "b6192296-4efa-4af5-ae02-1e31d28aae90", - "name": "male", - "type": "string", - "value": "Men" - }, - { - "id": "4b322294-940c-459d-b083-8e91e38193f7", - "name": "female", - "type": "string", - "value": "Women" - }, - { - "id": "1940eef0-6b76-4a26-9d8f-7c8536fbcb1b", - "name": "trans", - "type": "string", - "value": "Transgender and/or Non-Binary" - }, - { - "id": "3dba3e18-2bb1-4078-bde9-9d187f9628dd", - "name": "hetero", - "type": "string", - "value": "Heterosexual" - }, - { - "id": "9b7d10ad-1766-4b18-a230-3bd80142b48c", - "name": "lgbtqia", - "type": "string", - "value": "LGBTQ+" - }, - { - "id": "458636f8-99e8-4245-9950-94e4cf68e371", - "name": "nondisabled", - "type": "string", - "value": "Non-Disabled" - }, - { - "id": "a466e258-7de1-4453-a126-55f780094236", - "name": "disabled", - "type": "string", - "value": "People with Disabilities" - }, - { - "id": "98735266-0451-432f-be7c-efcb09512cb1", - "name": "caregiver", - "type": "string", - "value": "Caregivers" - }, - { - "id": "ebe2353c-9ff5-47bc-8c11-b66d3436f5b4", - "name": "parent", - "type": "string", - "value": "Parents/Guardians" - }, - { - "id": "ab51c80c-d81d-41ab-94d9-c0a263743c17", - "name": "nonparent", - "type": "string", - "value": "Not a Parent or Caregiver" - }, - { - "id": "cb7df429-c600-43f4-aa7e-dbc2382a85a0", - "name": "nonveteran", - "type": "string", - "value": "Non-Veterans" - }, - { - "id": "dffbdb13-189a-462d-83d1-c5ec39a17d41", - "name": "veteran", - "type": "string", - "value": "Veterans" - } - ] - }, - "includeOtherFields": true - }, - "typeVersion": 3.4 - }, - { - "id": "862f1c77-44a8-4d79-abac-33351ebb731b", - "name": "ScrapingBee Search Glassdoor", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 940, - 380 - ], - "parameters": { - "url": "https://app.scrapingbee.com/api/v1", - "options": {}, - "sendQuery": true, - "authentication": "genericCredentialType", - "genericAuthType": "httpQueryAuth", - "queryParameters": { - "parameters": [ - { - "name": "url", - "value": "=https://www.glassdoor.com/Search/results.htm?keyword={{ $json.company_name.toLowerCase().urlEncode() }}" - }, - { - "name": "premium_proxy", - "value": "true" - }, - { - "name": "block_resources", - "value": "false" - }, - { - "name": "stealth_proxy", - "value": "true" - } - ] - } - }, - "credentials": { - "httpQueryAuth": { - "id": "XXXXXX", - "name": "ScrapingBee Query Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "4c9bf05e-9c50-4895-b20b-b7c329104615", - "name": "Extract company url path", - "type": "n8n-nodes-base.html", - "position": [ - 1140, - 380 - ], - "parameters": { - "options": {}, - "operation": "extractHtmlContent", - "extractionValues": { - "values": [ - { - "key": "url_path", - "attribute": "href", - "cssSelector": "body main div a", - "returnValue": "attribute" - } - ] - } - }, - "typeVersion": 1.2 - }, - { - "id": "d20bb0e7-4ca7-41d0-a3e9-41abc811b064", - "name": "ScrapingBee GET company page contents", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 1340, - 380 - ], - "parameters": { - "url": "https://app.scrapingbee.com/api/v1", - "options": {}, - "sendQuery": true, - "authentication": "genericCredentialType", - "genericAuthType": "httpQueryAuth", - "queryParameters": { - "parameters": [ - { - "name": "url", - "value": "=https://www.glassdoor.com{{ $json.url_path }}" - }, - { - "name": "premium_proxy", - "value": "true" - }, - { - "name": "block_resources", - "value": "false" - }, - { - "name": "stealth_proxy", - "value": "true" - } - ] - } - }, - "credentials": { - "httpQueryAuth": { - "id": "XXXXXX", - "name": "ScrapingBee Query Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "fce70cab-8ce3-4ce2-b040-ce80d66b1e62", - "name": "Extract reviews page url path", - "type": "n8n-nodes-base.html", - "position": [ - 1540, - 380 - ], - "parameters": { - "options": {}, - "operation": "extractHtmlContent", - "extractionValues": { - "values": [ - { - "key": "url_path", - "attribute": "href", - "cssSelector": "#reviews a", - "returnValue": "attribute" - } - ] - } - }, - "typeVersion": 1.2 - }, - { - "id": "d2e7fee9-e3d4-42bf-8be6-38b352371273", - "name": "ScrapingBee GET Glassdoor Reviews Content", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 1760, - 380 - ], - "parameters": { - "url": "https://app.scrapingbee.com/api/v1", - "options": {}, - "sendQuery": true, - "authentication": "genericCredentialType", - "genericAuthType": "httpQueryAuth", - "queryParameters": { - "parameters": [ - { - "name": "url", - "value": "=https://www.glassdoor.com{{ $json.url_path }}" - }, - { - "name": "premium_proxy", - "value": "True" - }, - { - "name": "block_resources", - "value": "False" - }, - { - "name": "stealth_proxy", - "value": "true" - } - ] - } - }, - "credentials": { - "httpQueryAuth": { - "id": "XXXXXX", - "name": "ScrapingBee Query Auth" - } - }, - "typeVersion": 4.2 - }, - { - "id": "0c322823-0569-4bd5-9c4e-af3de0f8d7b4", - "name": "Extract Overall Review Summary", - "type": "n8n-nodes-base.html", - "position": [ - 1980, - 260 - ], - "parameters": { - "options": {}, - "operation": "extractHtmlContent", - "extractionValues": { - "values": [ - { - "key": "review_summary", - "cssSelector": "div[data-test=\"review-summary\"]", - "returnValue": "html" - } - ] - } - }, - "typeVersion": 1.2 - }, - { - "id": "851305ba-0837-4be9-943d-7282e8d74aee", - "name": "Extract Demographics Module", - "type": "n8n-nodes-base.html", - "position": [ - 1980, - 520 - ], - "parameters": { - "options": {}, - "operation": "extractHtmlContent", - "extractionValues": { - "values": [ - { - "key": "demographics_content", - "cssSelector": "div[data-test=\"demographics-module\"]", - "returnValue": "html" - } - ] - } - }, - "typeVersion": 1.2 - }, - { - "id": "cf9a6ee2-53b5-4fbf-a36c-4b9dab53b795", - "name": "Extract overall ratings and distribution percentages", - "type": "@n8n/n8n-nodes-langchain.informationExtractor", - "position": [ - 2200, - 200 - ], - "parameters": { - "text": "={{ $json.review_summary }}", - "options": {}, - "attributes": { - "attributes": [ - { - "name": "average_rating", - "type": "number", - "required": true, - "description": "The overall average rating for this company." - }, - { - "name": "total_number_of_reviews", - "type": "number", - "required": true, - "description": "The total number of reviews for this company." - }, - { - "name": "5_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 5 star reviews" - }, - { - "name": "4_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 4 star reviews" - }, - { - "name": "3_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 3 star reviews" - }, - { - "name": "2_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 2 star reviews" - }, - { - "name": "1_star_distribution_percentage", - "type": "number", - "required": true, - "description": "The percentage distribution of 1 star reviews" - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "ae164f6e-04e7-4d8b-951e-a17085956f4b", - "name": "Extract demographic distributions", - "type": "@n8n/n8n-nodes-langchain.informationExtractor", - "position": [ - 2200, - 620 - ], - "parameters": { - "text": "={{ $json.demographics_content }}", - "options": { - "systemPromptTemplate": "You are an expert extraction algorithm.\nOnly extract relevant information from the text.\nIf you do not know the value of an attribute asked to extract, you may use 0 for the attribute's value." - }, - "attributes": { - "attributes": [ - { - "name": "asian_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as asian." - }, - { - "name": "asian_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as asian." - }, - { - "name": "hispanic_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as hispanic." - }, - { - "name": "hispanic_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as hispanic." - }, - { - "name": "white_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as white." - }, - { - "name": "white_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as white." - }, - { - "name": "pacific_islander_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as native hawaiian or pacific islander." - }, - { - "name": "pacific_islander_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as native hawaiian or pacific islander." - }, - { - "name": "black_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as black." - }, - { - "name": "black_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as black." - }, - { - "name": "middle_eastern_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as middle eastern." - }, - { - "name": "middle_eastern_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as middle_eastern." - }, - { - "name": "indigenous_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as indigenous american or native alaskan." - }, - { - "name": "indigenous_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as indigenous american or native alaskan." - }, - { - "name": "male_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as men." - }, - { - "name": "male_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as men." - }, - { - "name": "female_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as women." - }, - { - "name": "female_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as women." - }, - { - "name": "trans_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as transgender and/or non-binary." - }, - { - "name": "trans_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as trans and/or non-binary." - }, - { - "name": "hetero_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as heterosexual." - }, - { - "name": "hetero_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as heterosexual." - }, - { - "name": "lgbtqia_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as lgbtqia+." - }, - { - "name": "lgbtqia_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as lgbtqia+." - }, - { - "name": "nondisabled_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as non-disabled." - }, - { - "name": "nondisabled_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as non-disabled." - }, - { - "name": "disabled_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as people with disabilities." - }, - { - "name": "disabled_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as people with disabilities." - }, - { - "name": "caregiver_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as caregivers." - }, - { - "name": "caregiver_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as caregivers." - }, - { - "name": "parent_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as parents/guardians." - }, - { - "name": "parent_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as parents/guardians." - }, - { - "name": "nonparent_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as not a parent or caregiver." - }, - { - "name": "nonparent_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as not a parent or guardian." - }, - { - "name": "nonveteran_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as non-veterans." - }, - { - "name": "nonveteran_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as non-veterans." - }, - { - "name": "veteran_average_rating", - "type": "number", - "required": true, - "description": "=The average rating for this company by employees who self identified as veterans." - }, - { - "name": "veteran_total_number_of_reviews", - "type": "number", - "required": true, - "description": "=The number of reviews for this company by employees who self-identified as veterans." - } - ] - } - }, - "typeVersion": 1 - }, - { - "id": "c8d9e45c-7d41-47bd-b9a9-0fa70de5d154", - "name": "Define contributions to variance", - "type": "n8n-nodes-base.set", - "position": [ - 2560, - 200 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "7360b2c2-1e21-45de-8d1a-e72b8abcb56b", - "name": "contribution_to_variance.5_star", - "type": "number", - "value": "={{ ($json.output['5_star_distribution_percentage'] / 100) * Math.pow(5 - $json.output.average_rating,2) }}" - }, - { - "id": "acdd308a-fa33-4e33-b71b-36b9441bfa06", - "name": "contribution_to_variance.4_star", - "type": "number", - "value": "={{ ($json.output['4_star_distribution_percentage'] / 100) * Math.pow(4 - $json.output.average_rating,2) }}" - }, - { - "id": "376818f3-d429-4abe-8ece-e8e9c5585826", - "name": "contribution_to_variance.3_star", - "type": "number", - "value": "={{ ($json.output['3_star_distribution_percentage'] / 100) * Math.pow(3 - $json.output.average_rating,2) }}" - }, - { - "id": "620d5c37-8b93-4d39-9963-b7ce3a7f431e", - "name": "contribution_to_variance.2_star", - "type": "number", - "value": "={{ ($json.output['2_star_distribution_percentage'] / 100) * Math.pow(2 - $json.output.average_rating,2) }}" - }, - { - "id": "76357980-4f9b-4b14-be68-6498ba25af67", - "name": "contribution_to_variance.1_star", - "type": "number", - "value": "={{ ($json.output['1_star_distribution_percentage'] / 100) * Math.pow(1 - $json.output.average_rating,2) }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "8ea03017-d5d6-46ef-a5f1-dae4372f6256", - "name": "Set variance and std_dev", - "type": "n8n-nodes-base.set", - "position": [ - 2740, - 200 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "3217d418-f1b0-45ff-9f9a-6e6145cc29ca", - "name": "variance", - "type": "number", - "value": "={{ $json.contribution_to_variance.values().sum() }}" - }, - { - "id": "acdb9fea-15ec-46ed-bde9-073e93597f17", - "name": "average_rating", - "type": "number", - "value": "={{ $('Extract overall ratings and distribution percentages').item.json.output.average_rating }}" - }, - { - "id": "1f3a8a29-4bd4-4b40-8694-c74a0285eadb", - "name": "total_number_of_reviews", - "type": "number", - "value": "={{ $('Extract overall ratings and distribution percentages').item.json.output.total_number_of_reviews }}" - }, - { - "id": "1906c796-1964-446b-8b56-d856269da938", - "name": "std_dev", - "type": "number", - "value": "={{ Math.sqrt($json.contribution_to_variance.values().sum()) }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "0570d531-8480-4446-8f02-18640b4b891e", - "name": "Calculate P-Scores", - "type": "n8n-nodes-base.code", - "position": [ - 3340, - 440 - ], - "parameters": { - "jsCode": "// Approximate CDF for standard normal distribution\nfunction normSDist(z) {\n const t = 1 / (1 + 0.3275911 * Math.abs(z));\n const d = 0.254829592 * t - 0.284496736 * t * t + 1.421413741 * t * t * t - 1.453152027 * t * t * t * t + 1.061405429 * t * t * t * t * t;\n return 0.5 * (1 + Math.sign(z) * d * Math.exp(-z * z / 2));\n}\n\nfor (const item of $input.all()) {\n if (!item.json.population_analysis.p_scores) {\n item.json.population_analysis.p_scores = {};\n }\n\n for (const score of Object.keys(item.json.population_analysis.z_scores)) {\n // Check if review count exists and is greater than zero\n if (item.json.population_analysis.review_count[score] > 0) {\n // Apply the p_score formula: 2 * NORM.S.DIST(-ABS(z_score))\n const p_score = 2 * normSDist(-Math.abs(item.json.population_analysis.z_scores[score]));\n\n // Store the calculated p_score\n item.json.population_analysis.p_scores[score] = p_score;\n } else {\n // Remove z_scores, effect_sizes, and p_scores for groups with no reviews\n delete item.json.population_analysis.z_scores[score];\n delete item.json.population_analysis.effect_sizes[score];\n delete item.json.population_analysis.p_scores[score];\n }\n }\n}\n\nreturn $input.all();" - }, - "typeVersion": 2 - }, - { - "id": "0bdb9732-67ef-440d-bdd2-42c4f64ff6b6", - "name": "Sort Effect Sizes", - "type": "n8n-nodes-base.set", - "position": [ - 3540, - 440 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "61cf92ba-bc4e-40b8-a234-9b993fd24019", - "name": "population_analysis.effect_sizes", - "type": "object", - "value": "={{ Object.fromEntries(Object.entries($json.population_analysis.effect_sizes).sort(([,a],[,b]) => a-b )) }}" - } - ] - }, - "includeOtherFields": true - }, - "typeVersion": 3.4 - }, - { - "id": "fd9026ef-e993-410a-87d6-40a3ad10b7a7", - "name": "Calculate Z-Scores and Effect Sizes", - "type": "n8n-nodes-base.set", - "position": [ - 3140, - 600 - ], - "parameters": { - "options": {}, - "assignments": { - "assignments": [ - { - "id": "790a53e8-5599-45d3-880e-ab1ad7d165d2", - "name": "population_analysis.z_scores.asian", - "type": "number", - "value": "={{ ($json.output.asian_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.asian_total_number_of_reviews)) }}" - }, - { - "id": "ebd61097-8773-45b9-a8e6-cdd840d73650", - "name": "population_analysis.effect_sizes.asian", - "type": "number", - "value": "={{ ($json.output.asian_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "627b1293-efdc-485a-83c8-bd332d6dc225", - "name": "population_analysis.z_scores.hispanic", - "type": "number", - "value": "={{ ($json.output.hispanic_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.hispanic_total_number_of_reviews)) }}" - }, - { - "id": "822028d0-e94f-4cf7-9e13-8f8cc5c72ec0", - "name": "population_analysis.z_scores.white", - "type": "number", - "value": "={{ ($json.output.white_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.white_total_number_of_reviews)) }}" - }, - { - "id": "d32321f9-0fcf-4e54-9059-c3fd5a901ce0", - "name": "population_analysis.z_scores.pacific_islander", - "type": "number", - "value": "={{ ($json.output.pacific_islander_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.pacific_islander_total_number_of_reviews)) }}" - }, - { - "id": "e212d683-247f-45c4-9668-c290230a10ed", - "name": "population_analysis.z_scores.black", - "type": "number", - "value": "={{ ($json.output.black_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.black_total_number_of_reviews)) }}" - }, - { - "id": "882049c3-eb81-4c09-af0c-5c79b0ef0154", - "name": "population_analysis.z_scores.middle_eastern", - "type": "number", - "value": "={{ ($json.output.middle_eastern_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.middle_eastern_total_number_of_reviews)) }}" - }, - { - "id": "9bdc187f-3d8d-4030-9143-479eff441b7e", - "name": "population_analysis.z_scores.indigenous", - "type": "number", - "value": "={{ ($json.output.indigenous_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.indigenous_total_number_of_reviews)) }}" - }, - { - "id": "0cf11453-dbae-4250-a01a-c98e35aab224", - "name": "population_analysis.z_scores.male", - "type": "number", - "value": "={{ ($json.output.male_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.male_total_number_of_reviews)) }}" - }, - { - "id": "35a18fbc-7c2c-40fe-829d-2fffbdb13bb8", - "name": "population_analysis.z_scores.female", - "type": "number", - "value": "={{ ($json.output.female_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.female_total_number_of_reviews)) }}" - }, - { - "id": "a6e17c1b-a89b-4c05-8184-10f7248c159f", - "name": "population_analysis.z_scores.trans", - "type": "number", - "value": "={{ ($json.output.trans_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.trans_total_number_of_reviews)) }}" - }, - { - "id": "5e7dbccf-3011-4dba-863c-5390c1ee9e50", - "name": "population_analysis.z_scores.hetero", - "type": "number", - "value": "={{ ($json.output.hetero_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.hetero_total_number_of_reviews)) }}" - }, - { - "id": "1872152f-2c7e-4c24-bcd5-e2777616bfe2", - "name": "population_analysis.z_scores.lgbtqia", - "type": "number", - "value": "={{ ($json.output.lgbtqia_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.lgbtqia_total_number_of_reviews)) }}" - }, - { - "id": "91b2cb00-173e-421a-929a-51d2a6654767", - "name": "population_analysis.z_scores.nondisabled", - "type": "number", - "value": "={{ ($json.output.nondisabled_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.nondisabled_total_number_of_reviews)) }}" - }, - { - "id": "8bb7429e-0500-482c-8e8d-d2c63733ffe1", - "name": "population_analysis.z_scores.disabled", - "type": "number", - "value": "={{ ($json.output.disabled_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.disabled_total_number_of_reviews)) }}" - }, - { - "id": "89f00d0f-80db-4ad9-bf60-9385aa3d915b", - "name": "population_analysis.z_scores.caregiver", - "type": "number", - "value": "={{ ($json.output.caregiver_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.caregiver_total_number_of_reviews)) }}" - }, - { - "id": "0bb2b96c-d882-4ac1-9432-9fce06b26cf5", - "name": "population_analysis.z_scores.parent", - "type": "number", - "value": "={{ ($json.output.parent_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.parent_total_number_of_reviews)) }}" - }, - { - "id": "9aae7169-1a25-4fab-b940-7f2cd7ef39d9", - "name": "population_analysis.z_scores.nonparent", - "type": "number", - "value": "={{ ($json.output.nonparent_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.nonparent_total_number_of_reviews)) }}" - }, - { - "id": "aac189a0-d6fc-4581-a15d-3e75a0cb370a", - "name": "population_analysis.z_scores.nonveteran", - "type": "number", - "value": "={{ ($json.output.nonveteran_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.nonveteran_total_number_of_reviews)) }}" - }, - { - "id": "d40f014a-9c1d-4aea-88ac-d8a3de143931", - "name": "population_analysis.z_scores.veteran", - "type": "number", - "value": "={{ ($json.output.veteran_average_rating - $json.average_rating) / ($json.std_dev / Math.sqrt($json.output.veteran_total_number_of_reviews)) }}" - }, - { - "id": "67e0394f-6d55-4e80-8a7d-814635620b1d", - "name": "population_analysis.effect_sizes.hispanic", - "type": "number", - "value": "={{ ($json.output.hispanic_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "65cd3a22-2c97-4da1-8fcc-cc1af39118f2", - "name": "population_analysis.effect_sizes.white", - "type": "number", - "value": "={{ ($json.output.white_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "a03bdf0f-e294-4a01-bb08-ddc16e9997a5", - "name": "population_analysis.effect_sizes.pacific_islander", - "type": "number", - "value": "={{ ($json.output.pacific_islander_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "b0bdc40e-ed5f-475b-9d8b-8cf5beff7002", - "name": "population_analysis.effect_sizes.black", - "type": "number", - "value": "={{ ($json.output.black_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "45cac3f0-7270-4fa4-8fc4-94914245a77d", - "name": "population_analysis.effect_sizes.middle_eastern", - "type": "number", - "value": "={{ ($json.output.middle_eastern_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "cf5b7650-8766-45f6-8241-49aea62bf619", - "name": "population_analysis.effect_sizes.indigenous", - "type": "number", - "value": "={{ ($json.output.indigenous_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "7c6a8d38-02b7-47a1-af44-5eebfb4140ec", - "name": "population_analysis.effect_sizes.male", - "type": "number", - "value": "={{ ($json.output.male_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "4bf3dba9-4d07-4315-83ce-5fba288a00c9", - "name": "population_analysis.effect_sizes.female", - "type": "number", - "value": "={{ ($json.output.female_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "d5e980b8-d7a8-4d4c-bcd9-fd9cbd20c729", - "name": "population_analysis.effect_sizes.trans", - "type": "number", - "value": "={{ ($json.output.trans_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "2c8271c1-b612-4292-9d48-92c342b83727", - "name": "population_analysis.effect_sizes.hetero", - "type": "number", - "value": "={{ ($json.output.hetero_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "996f2ea0-2e46-424b-9797-2d58fd56b1d3", - "name": "population_analysis.effect_sizes.lgbtqia", - "type": "number", - "value": "={{ ($json.output.lgbtqia_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "8c987b6e-764d-422e-82de-00bd89269b22", - "name": "population_analysis.effect_sizes.nondisabled", - "type": "number", - "value": "={{ ($json.output.nondisabled_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "ab796bb7-06ff-4282-b4b3-eefd129c743e", - "name": "population_analysis.effect_sizes.disabled", - "type": "number", - "value": "={{ ($json.output.disabled_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "a17bf413-a098-4f24-8162-821a6a0ddb5e", - "name": "population_analysis.effect_sizes.caregiver", - "type": "number", - "value": "={{ ($json.output.caregiver_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "99911e1e-06e8-4bbd-915d-b92b8b37b374", - "name": "population_analysis.effect_sizes.parent", - "type": "number", - "value": "={{ ($json.output.parent_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "4ddf729b-361e-4d81-a67c-b6c18509e60b", - "name": "population_analysis.effect_sizes.nonparent", - "type": "number", - "value": "={{ ($json.output.nonparent_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "725b8abb-7f72-45fc-a0c0-0e0a4f2cb131", - "name": "population_analysis.effect_sizes.nonveteran", - "type": "number", - "value": "={{ ($json.output.nonveteran_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "20e54fa5-2faa-4134-90e5-81224ec9659e", - "name": "population_analysis.effect_sizes.veteran", - "type": "number", - "value": "={{ ($json.output.veteran_average_rating - $json.average_rating) / $json.std_dev }}" - }, - { - "id": "2cc6465a-3a1c-4eb5-9e5a-72d41049d81e", - "name": "population_analysis.review_count.asian", - "type": "number", - "value": "={{ $json.output.asian_total_number_of_reviews }}" - }, - { - "id": "0a5f6aae-ba21-47b5-8af8-fec2256e4df6", - "name": "population_analysis.review_count.hispanic", - "type": "number", - "value": "={{ $json.output.hispanic_total_number_of_reviews }}" - }, - { - "id": "ae124587-7e24-4c1a-a002-ed801f859c30", - "name": "population_analysis.review_count.pacific_islander", - "type": "number", - "value": "={{ $json.output.pacific_islander_total_number_of_reviews }}" - }, - { - "id": "fc790196-ca8e-4069-a093-87a413ebbf3e", - "name": "population_analysis.review_count.black", - "type": "number", - "value": "={{ $json.output.black_total_number_of_reviews }}" - }, - { - "id": "7fd72701-781e-4e33-b000-174a853b172b", - "name": "population_analysis.review_count.middle_eastern", - "type": "number", - "value": "={{ $json.output.middle_eastern_total_number_of_reviews }}" - }, - { - "id": "3751e7da-11a7-4af3-8aa6-1c6d53bcf27d", - "name": "population_analysis.review_count.indigenous", - "type": "number", - "value": "={{ $json.output.indigenous_total_number_of_reviews }}" - }, - { - "id": "9ee0cac9-d2dd-4ba0-90ee-b2cdd22d9b77", - "name": "population_analysis.review_count.male", - "type": "number", - "value": "={{ $json.output.male_total_number_of_reviews }}" - }, - { - "id": "ae7fcdc7-d373-4c24-9a65-94bd2b5847a8", - "name": "population_analysis.review_count.female", - "type": "number", - "value": "={{ $json.output.female_total_number_of_reviews }}" - }, - { - "id": "3f53d065-269f-425a-b27d-dc5a3dbb6141", - "name": "population_analysis.review_count.trans", - "type": "number", - "value": "={{ $json.output.trans_total_number_of_reviews }}" - }, - { - "id": "d15e976e-7599-4df0-9e65-8047b7a4cda8", - "name": "population_analysis.review_count.hetero", - "type": "number", - "value": "={{ $json.output.hetero_total_number_of_reviews }}" - }, - { - "id": "c8b786d3-a980-469f-bf0e-de70ad44f0ea", - "name": "population_analysis.review_count.lgbtqia", - "type": "number", - "value": "={{ $json.output.lgbtqia_total_number_of_reviews }}" - }, - { - "id": "e9429215-0858-4482-964a-75de7978ecbb", - "name": "population_analysis.review_count.nondisabled", - "type": "number", - "value": "={{ $json.output.nondisabled_total_number_of_reviews }}" - }, - { - "id": "2c6e53c4-eab1-42aa-b956-ee882832f569", - "name": "population_analysis.review_count.disabled", - "type": "number", - "value": "={{ $json.output.disabled_total_number_of_reviews }}" - }, - { - "id": "b5edfa25-ab11-4b94-9670-4d5589a62498", - "name": "population_analysis.review_count.caregiver", - "type": "number", - "value": "={{ $json.output.caregiver_total_number_of_reviews }}" - }, - { - "id": "41084e96-c42f-4bb0-ac1a-883b46537fca", - "name": "population_analysis.review_count.parent", - "type": "number", - "value": "={{ $json.output.parent_total_number_of_reviews }}" - }, - { - "id": "96496a38-9311-4ade-bd2f-2943d1d92314", - "name": "population_analysis.review_count.nonparent", - "type": "number", - "value": "={{ $json.output.nonparent_total_number_of_reviews }}" - }, - { - "id": "5071771d-5f41-43cb-a8ce-e4e40ed3519b", - "name": "population_analysis.review_count.nonveteran", - "type": "number", - "value": "={{ $json.output.nonveteran_total_number_of_reviews }}" - }, - { - "id": "2358e782-70da-4964-b625-5fe1946b5250", - "name": "population_analysis.review_count.veteran", - "type": "number", - "value": "={{ $json.output.veteran_total_number_of_reviews }}" - } - ] - } - }, - "typeVersion": 3.4 - }, - { - "id": "85536931-839a-476b-b0dd-fa6d01c6d5c1", - "name": "Format dataset for scatterplot", - "type": "n8n-nodes-base.code", - "position": [ - 3340, - 760 - ], - "parameters": { - "jsCode": "// Iterate through the input data and format the dataset for QuickChart\nfor (const item of $input.all()) {\n // Ensure the data object exists and initialize datasets\n item.json.data = {\n datasets: []\n };\n\n const z_scores = item.json.population_analysis.z_scores;\n const effect_sizes = item.json.population_analysis.effect_sizes;\n const review_count = item.json.population_analysis.review_count;\n\n // Ensure z_scores, effect_sizes, and review_count are defined and are objects\n if (z_scores && effect_sizes && review_count && typeof z_scores === 'object' && typeof effect_sizes === 'object' && typeof review_count === 'object') {\n // Initialize the dataset object\n const dataset = {\n label: 'Demographics Data',\n data: []\n };\n\n // Iterate through the demographic keys\n for (const key in z_scores) {\n // Check if review count for the demographic is greater than 0\n if (z_scores.hasOwnProperty(key) && effect_sizes.hasOwnProperty(key) && review_count[key] > 0) {\n\n // Add each demographic point to the dataset\n dataset.data.push({\n x: z_scores[key], // x = z_score\n y: effect_sizes[key], // y = effect_size\n label: $('Define dictionary of demographic keys').first().json[key],\n });\n }\n }\n\n // Only add the dataset if it contains data\n if (dataset.data.length > 0) {\n item.json.data.datasets.push(dataset);\n }\n\n delete item.json.population_analysis\n }\n}\n\n// Return the updated input with the data object containing datasets and labels\nreturn $input.all();\n" - }, - "typeVersion": 2 - }, - { - "id": "957b9f6c-7cf8-4ec6-aec7-a7d59ed3a4ad", - "name": "Specify additional parameters for scatterplot", - "type": "n8n-nodes-base.set", - "position": [ - 3540, - 760 - ], - "parameters": { - "options": { - "ignoreConversionErrors": false - }, - "assignments": { - "assignments": [ - { - "id": "5cd507f6-6835-4d2e-8329-1b5d24a3fc15", - "name": "type", - "type": "string", - "value": "scatter" - }, - { - "id": "80b6f981-e3c7-4c6e-a0a1-f30d028fe15e", - "name": "options", - "type": "object", - "value": "={\n \"title\": {\n \"display\": true,\n \"position\": \"top\",\n \"fontSize\": 12,\n \"fontFamily\": \"sans-serif\",\n \"fontColor\": \"#666666\",\n \"fontStyle\": \"bold\",\n \"padding\": 10,\n \"lineHeight\": 1.2,\n \"text\": \"{{ $('SET company_name').item.json.company_name }} Workplace Population Bias\"\n },\n \"legend\": {\n \"display\": false\n },\n \"scales\": {\n \"xAxes\": [\n {\n \"scaleLabel\": {\n \"display\": true,\n \"labelString\": \"Z-Score\",\n \"fontColor\": \"#666666\",\n \"fontSize\": 12,\n \"fontFamily\": \"sans-serif\"\n }\n }\n ],\n \"yAxes\": [\n {\n \"scaleLabel\": {\n \"display\": true,\n \"labelString\": \"Effect Score\",\n \"fontColor\": \"#666666\",\n \"fontSize\": 12,\n \"fontFamily\": \"sans-serif\"\n }\n }\n ]\n },\n \"plugins\": {\n \"datalabels\": {\n \"display\": true,\n \"align\": \"top\",\n \"anchor\": \"center\",\n \"backgroundColor\": \"#eee\",\n \"borderColor\": \"#ddd\",\n \"borderRadius\": 6,\n \"borderWidth\": 1,\n \"padding\": 4,\n \"color\": \"#000\",\n \"font\": {\n \"family\": \"sans-serif\",\n \"size\": 10,\n \"style\": \"normal\"\n }\n }\n }\n }" - } - ] - }, - "includeOtherFields": true - }, - "typeVersion": 3.4 - }, - { - "id": "a937132c-43fc-4fa0-ae35-885da89e51d1", - "name": "Quickchart Scatterplot", - "type": "n8n-nodes-base.httpRequest", - "position": [ - 3740, - 760 - ], - "parameters": { - "url": "https://quickchart.io/chart", - "options": {}, - "sendQuery": true, - "queryParameters": { - "parameters": [ - { - "name": "c", - "value": "={{ $json.toJsonString() }}" - }, - { - "name": "Content-Type", - "value": "application/json" - }, - { - "name": "encoding", - "value": "url" - } - ] - } - }, - "typeVersion": 4.2 - }, - { - "id": "ede1931e-bac8-4279-b3a7-5980a190e324", - "name": "QuickChart Bar Chart", - "type": "n8n-nodes-base.quickChart", - "position": [ - 3740, - 560 - ], - "parameters": { - "data": "={{ $json.population_analysis.effect_sizes.values() }}", - "output": "bar_chart", - "labelsMode": "array", - "labelsArray": "={{ $json.population_analysis.effect_sizes.keys() }}", - "chartOptions": { - "format": "png" - }, - "datasetOptions": { - "label": "={{ $('SET company_name').item.json.company_name }} Effect Size on Employee Experience" - } - }, - "typeVersion": 1 - }, - { - "id": "6122fec0-619c-48d3-ad2c-05ed55ba2275", - "name": "Sticky Note", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 480, - 40 - ], - "parameters": { - "color": 7, - "width": 3741.593083126444, - "height": 1044.8111554136713, - "content": "# Spot Workplace Discrimination Patterns using ScrapingBee, Glassdoor, OpenAI, and QuickChart\n" - }, - "typeVersion": 1 - }, - { - "id": "5cda63e8-f31b-46f6-8cb2-41d1856ac537", - "name": "Sticky Note1", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 900, - 180 - ], - "parameters": { - "color": 4, - "width": 1237.3377621763516, - "height": 575.9439659309116, - "content": "## Use ScrapingBee to gather raw data from Glassdoor" - }, - "typeVersion": 1 - }, - { - "id": "28d247b2-9020-4280-83d2-d6583622c0b7", - "name": "Sticky Note2", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 920, - 240 - ], - "parameters": { - "color": 7, - "width": 804.3951263154196, - "height": 125.73173301324687, - "content": "### Due to javascript restrictions, a normal HTTP request cannot be used to gather user-reported details from Glassdoor. \n\nInstead, [ScrapingBee](https://www.scrapingbee.com/) offers a great tool with a very generous package of free tokens per month, which works out to roughly 4-5 runs of this workflow." - }, - "typeVersion": 1 - }, - { - "id": "d65a239c-06d2-470b-b24a-23ec00a9f148", - "name": "Sticky Note3", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2180, - 99.69933502879758 - ], - "parameters": { - "color": 5, - "width": 311.0523273992095, - "height": 843.8786512173932, - "content": "## Extract details with AI" - }, - "typeVersion": 1 - }, - { - "id": "3cffd188-62a1-43a7-a67f-548e21d2b187", - "name": "Sticky Note4", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2516.1138215303854, - 100 - ], - "parameters": { - "color": 7, - "width": 423.41585047129973, - "height": 309.71740416262054, - "content": "### Calculate variance and standard deviation from review rating distributions." - }, - "typeVersion": 1 - }, - { - "id": "b5015c07-03e3-47d4-9469-e831b2c755c0", - "name": "Sticky Note6", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 3320, - 706.46982689582 - ], - "parameters": { - "color": 5, - "width": 639.5579220386832, - "height": 242.80759628871897, - "content": "## Formatting datasets for Scatterplot" - }, - "typeVersion": 1 - }, - { - "id": "e52bb9d9-617a-46f5-b217-a6f670b6714c", - "name": "Sticky Note7", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 500, - 120 - ], - "parameters": { - "width": 356.84794255678776, - "height": 186.36110628732342, - "content": "## How this workflow works\n1. Replace ScrapingBee and OpenAI credentials\n2. Replace company_name with company of choice (workflow performs better with larger US-based organizations)\n3. Preview QuickChart data visualizations and AI data analysis" - }, - "typeVersion": 1 - }, - { - "id": "d83c07a3-04ed-418f-94f1-e70828cba8b2", - "name": "Sticky Note8", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 500, - 880 - ], - "parameters": { - "color": 6, - "width": 356.84794255678776, - "height": 181.54335665904924, - "content": "### Inspired by [Wes Medford's Medium Post](https://medium.com/@wryanmedford/an-open-letter-to-twilios-leadership-f06f661ecfb4)\n\nWes performed the initial data analysis highlighting problematic behaviors at Twilio. I wanted to try and democratize the data analysis they performed for those less technical.\n\n**Hi, Wes!**" - }, - "typeVersion": 1 - }, - { - "id": "ed0c1b4a-99fe-4a27-90bb-ac38dd20810b", - "name": "Sticky Note9", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 4020, - 880 - ], - "parameters": { - "color": 7, - "width": 847.5931795867759, - "height": 522.346478008115, - "content": "![image](https://quickchart.io/chart?c=%7B%0A%20%20%22type%22%3A%20%22scatter%22%2C%0A%20%20%22data%22%3A%20%7B%0A%20%20%20%20%22datasets%22%3A%20%5B%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%22label%22%3A%20%22Demographics%20Data%22%2C%0A%20%20%20%20%20%20%20%20%22data%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%201.1786657494327952%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%200.16190219204909295%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%200.5119796850491362%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%200.0809510960245463%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-0.9300572848378476%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.16190219204909329%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-0.42835293687811976%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.16190219204909329%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.0890856121128139%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.08095109602454664%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.7362075843299012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.16190219204909329%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-2.9142394568836774%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.971413152294559%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.2088576542791578%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.08095109602454664%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-2.5276971632072494%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.4047554801227329%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%200%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%200%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-5.504674529669168%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-1.376168632417292%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-0.8412684674574105%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.24285328807363996%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-2.896194457023989%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.32380438409818657%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.0303392409819254%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.08095109602454664%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20-1.2670850749479952%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.08095109602454664%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%201.535939055147413%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%200.4857065761472792%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%2C%0A%20%20%20%20%22labels%22%3A%20%5B%0A%20%20%20%20%20%20%22asian%22%2C%0A%20%20%20%20%20%20%22hispanic%22%2C%0A%20%20%20%20%20%20%22black%22%2C%0A%20%20%20%20%20%20%22middle_eastern%22%2C%0A%20%20%20%20%20%20%22male%22%2C%0A%20%20%20%20%20%20%22female%22%2C%0A%20%20%20%20%20%20%22trans%22%2C%0A%20%20%20%20%20%20%22hetero%22%2C%0A%20%20%20%20%20%20%22lgbtqia%22%2C%0A%20%20%20%20%20%20%22nondisabled%22%2C%0A%20%20%20%20%20%20%22disabled%22%2C%0A%20%20%20%20%20%20%22caregiver%22%2C%0A%20%20%20%20%20%20%22parent%22%2C%0A%20%20%20%20%20%20%22nonparent%22%2C%0A%20%20%20%20%20%20%22nonveteran%22%2C%0A%20%20%20%20%20%20%22veteran%22%0A%20%20%20%20%5D%0A%20%20%7D%2C%0A%20%20%22options%22%3A%20%7B%0A%20%20%20%20%22title%22%3A%20%7B%0A%20%20%20%20%20%20%22display%22%3A%20true%2C%0A%20%20%20%20%20%20%22position%22%3A%20%22top%22%2C%0A%20%20%20%20%20%20%22fontSize%22%3A%2012%2C%0A%20%20%20%20%20%20%22fontFamily%22%3A%20%22sans-serif%22%2C%0A%20%20%20%20%20%20%22fontColor%22%3A%20%22%23666666%22%2C%0A%20%20%20%20%20%20%22fontStyle%22%3A%20%22bold%22%2C%0A%20%20%20%20%20%20%22padding%22%3A%2010%2C%0A%20%20%20%20%20%20%22lineHeight%22%3A%201.2%2C%0A%20%20%20%20%20%20%22text%22%3A%20%22Twilio%20Workplace%20Population%20Bias%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22legend%22%3A%20%7B%0A%20%20%20%20%20%20%22display%22%3A%20false%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22scales%22%3A%20%7B%0A%20%20%20%20%20%20%22xAxes%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22scaleLabel%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22display%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22labelString%22%3A%20%22Z-Score%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontColor%22%3A%20%22%23666666%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontSize%22%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontFamily%22%3A%20%22sans-serif%22%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%22yAxes%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22scaleLabel%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22display%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22labelString%22%3A%20%22Effect%20Score%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontColor%22%3A%20%22%23666666%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontSize%22%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22fontFamily%22%3A%20%22sans-serif%22%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%5D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22plugins%22%3A%20%7B%0A%20%20%20%20%20%20%22datalabels%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22display%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%22align%22%3A%20%22top%22%2C%0A%20%20%20%20%20%20%20%20%22anchor%22%3A%20%22center%22%2C%0A%20%20%20%20%20%20%20%20%22backgroundColor%22%3A%20%22%23eee%22%2C%0A%20%20%20%20%20%20%20%20%22borderColor%22%3A%20%22%23ddd%22%2C%0A%20%20%20%20%20%20%20%20%22borderRadius%22%3A%206%2C%0A%20%20%20%20%20%20%20%20%22borderWidth%22%3A%201%2C%0A%20%20%20%20%20%20%20%20%22padding%22%3A%204%2C%0A%20%20%20%20%20%20%20%20%22color%22%3A%20%22%23000%22%2C%0A%20%20%20%20%20%20%20%20%22font%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22family%22%3A%20%22sans-serif%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22size%22%3A%2010%2C%0A%20%20%20%20%20%20%20%20%20%20%22style%22%3A%20%22normal%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22formatter%22%3A%20function(value%2C%20context)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20idx%20%3D%20context.dataIndex%3B%0A%20%20%20%20%20%20%20%20%20%20return%20context.chart.data.labels%5Bidx%5D%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A#full-width)" - }, - "typeVersion": 1 - }, - { - "id": "7b92edf8-3a58-4931-abf4-d9c2f57cfa32", - "name": "Sticky Note10", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 3980, - 800 - ], - "parameters": { - "color": 6, - "width": 989.7621518164046, - "height": 636.6345107975716, - "content": "## Example Scatterplot output" - }, - "typeVersion": 1 - }, - { - "id": "bd6859b4-096c-401e-9bce-91e970e1afd1", - "name": "Sticky Note11", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 2540, - 800 - ], - "parameters": { - "color": 6, - "width": 737.6316136259719, - "height": 444.9087184962878, - "content": "## Glossary\n**Z-Score** – A statistical measure that indicates how many standard deviations a data point is from the mean. In this analysis, a negative z-score suggests a group rates their workplace experience lower than the average, while a positive z-score suggests a better-than-average experience.\n\n**Effect Size** – A measure of the magnitude of difference between groups. Larger negative effect sizes indicate a more substantial disparity in workplace experiences for certain groups, making it useful for identifying meaningful gaps beyond just statistical significance.\n\n**P-Score (P-Value)** – The probability that the observed differences occurred by chance. A lower p-score (typically below 0.05) suggests the difference is statistically significant and unlikely to be random. In this analysis, high p-scores confirm that the disparities in ratings for marginalized groups are unlikely to be due to chance alone.\n\n### Relevance to This Analysis\nThese metrics help quantify workplace disparities among demographic groups. Z-scores show which groups report better or worse experiences, effect sizes reveal the severity of these differences, and p-scores confirm whether the disparities are statistically meaningful. This data allows for a more informed discussion about workplace equity and areas needing improvement." - }, - "typeVersion": 1 - }, - { - "id": "5af3ef87-ed4b-481e-b1ba-d44ffb7551d8", - "name": "Sticky Note12", - "type": "n8n-nodes-base.stickyNote", - "position": [ - 4140, - 80 - ], - "parameters": { - "color": 6, - "width": 643.5995639515581, - "height": 646.0030521944287, - "content": "## Example AI Analysis (Twilio Example)\n\n### Key Takeaways\n1. **Significant Disparity Among Disabled Employees**\nDisabled employees reported the lowest average ratings, with a z-score of -5.50, indicating a far worse experience compared to their non-disabled peers. \n2. **LGBTQIA Community's Challenges**\nMembers of the LGBTQIA community showed significantly lower ratings (z-score of -2.53), suggesting they may experience a workplace environment that is less inclusive or supportive compared to others.\n3. **Transgender Experiences Are Particularly Negative**\nTransgender employees rated their experiences considerably lower (z-score of -2.91), highlighting a critical area for improvement in workplace culture and acceptance.\n4. **Veterans Report Higher Satisfaction**\nIn contrast, veterans had the highest ratings (z-score of 1.54), which could indicate a supportive environment or programs tailored to their needs.\n5. **Overall Gender Discrepancies**\nA noticeable gap exists in average ratings by gender, with female employees scoring below male employees, suggesting potential gender biases or challenges in workplace dynamics.\n\n### Employee Experiences\n#### Perceptions of Workplace Environment\nFor members of groups reporting significantly worse experiences, such as disabled, transgender, and LGBTQIA employees, the workplace may feel alienating or unwelcoming. These individuals might perceive that their contributions are undervalued or overlooked and that necessary support systems are lacking, creating a culture of exclusion rather than one of inclusivity. This feeling of being marginalized can lead to poorer engagement, higher turnover rates, and diminished overall job satisfaction, adversely impacting both employees and the organization." - }, - "typeVersion": 1 - }, - { - "id": "a39cdbe7-d6ae-4a84-98c7-52ebf98242f3", - "name": "Text Analysis of Bias Data", - "type": "@n8n/n8n-nodes-langchain.chainLlm", - "position": [ - 3720, - 280 - ], - "parameters": { - "text": "=This data compares the average rating given by different demographic groups against a baseline (the overall mean rating).\n\nObjective:\n1. Analyze the data and offer between 2 and 5 key takeaways with a title and short (one-sentence) summary.\n2. Below the key takeaways, Include a heading called \"Employee Experiences\". Under this heading, include a subheader and paragraph describing the possible perception of the workplace for members of any groups reporting significantly worse (or better) experiences than others.\n3. Ensure there are between 2-5 key takeaways and employee experiences\n\nData for analysis:\n{{ $json.population_analysis.toJsonString() }}", - "promptType": "define" - }, - "typeVersion": 1.4 - } - ], - "active": false, - "pinData": {}, - "settings": { - "executionOrder": "v1" - }, - "versionId": "ff1df786-ebaf-4ed0-aeca-1872b93ef275", - "connections": { - "Merge": { - "main": [ - [ - { - "node": "Calculate Z-Scores and Effect Sizes", - "type": "main", - "index": 0 - } - ] - ] - }, - "SET company_name": { - "main": [ - [ - { - "node": "Define dictionary of demographic keys", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model": { - "ai_languageModel": [ - [ - { - "node": "Text Analysis of Bias Data", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "Sort Effect Sizes": { - "main": [ - [ - { - "node": "QuickChart Bar Chart", - "type": "main", - "index": 0 - }, - { - "node": "Text Analysis of Bias Data", - "type": "main", - "index": 0 - } - ] - ] - }, - "Calculate P-Scores": { - "main": [ - [ - { - "node": "Sort Effect Sizes", - "type": "main", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model1": { - "ai_languageModel": [ - [ - { - "node": "Extract demographic distributions", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "OpenAI Chat Model2": { - "ai_languageModel": [ - [ - { - "node": "Extract overall ratings and distribution percentages", - "type": "ai_languageModel", - "index": 0 - } - ] - ] - }, - "Extract company url path": { - "main": [ - [ - { - "node": "ScrapingBee GET company page contents", - "type": "main", - "index": 0 - } - ] - ] - }, - "Set variance and std_dev": { - "main": [ - [ - { - "node": "Merge", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract Demographics Module": { - "main": [ - [ - { - "node": "Extract demographic distributions", - "type": "main", - "index": 0 - } - ] - ] - }, - "ScrapingBee Search Glassdoor": { - "main": [ - [ - { - "node": "Extract company url path", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract reviews page url path": { - "main": [ - [ - { - "node": "ScrapingBee GET Glassdoor Reviews Content", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract Overall Review Summary": { - "main": [ - [ - { - "node": "Extract overall ratings and distribution percentages", - "type": "main", - "index": 0 - } - ] - ] - }, - "Format dataset for scatterplot": { - "main": [ - [ - { - "node": "Specify additional parameters for scatterplot", - "type": "main", - "index": 0 - } - ] - ] - }, - "Define contributions to variance": { - "main": [ - [ - { - "node": "Set variance and std_dev", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract demographic distributions": { - "main": [ - [ - { - "node": "Merge", - "type": "main", - "index": 1 - } - ] - ] - }, - "When clicking β€˜Test workflow’": { - "main": [ - [ - { - "node": "SET company_name", - "type": "main", - "index": 0 - } - ] - ] - }, - "Calculate Z-Scores and Effect Sizes": { - "main": [ - [ - { - "node": "Calculate P-Scores", - "type": "main", - "index": 0 - }, - { - "node": "Format dataset for scatterplot", - "type": "main", - "index": 0 - } - ] - ] - }, - "Define dictionary of demographic keys": { - "main": [ - [ - { - "node": "ScrapingBee Search Glassdoor", - "type": "main", - "index": 0 - } - ] - ] - }, - "ScrapingBee GET company page contents": { - "main": [ - [ - { - "node": "Extract reviews page url path", - "type": "main", - "index": 0 - } - ] - ] - }, - "ScrapingBee GET Glassdoor Reviews Content": { - "main": [ - [ - { - "node": "Extract Demographics Module", - "type": "main", - "index": 0 - }, - { - "node": "Extract Overall Review Summary", - "type": "main", - "index": 0 - } - ] - ] - }, - "Specify additional parameters for scatterplot": { - "main": [ - [ - { - "node": "Quickchart Scatterplot", - "type": "main", - "index": 0 - } - ] - ] - }, - "Extract overall ratings and distribution percentages": { - "main": [ - [ - { - "node": "Define contributions to variance", - "type": "main", - "index": 0 - } - ] - ] - } - } -} \ No newline at end of file