> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hans.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Notifications

> Understanding notification tasks and how they work

## Overview

Notification tasks are the core of hans.ai. They define:

* **What** to monitor (URL)
* **How** to evaluate changes (evaluation function)
* **When** to check (schedule)
* **What** to do when conditions are met (actions)

## Creating a Notification Task

### Basic Structure

```javascript theme={null}
{
  "name": "Product Price Monitor",
  "description": "Monitor price changes for a specific product",
  "url": "https://example.com/product/123",
  "evaluationFunction": "// JavaScript code to evaluate the page",
  "zodSchema": "// Optional Zod schema for data extraction",
  "actions": [
    // Array of action configurations
  ],
  "schedule": {
    "cron": "*/30 * * * *" // Check every 30 minutes
  }
}
```

## Evaluation Functions

Evaluation functions are JavaScript code that runs in the context of the monitored page. They determine whether to trigger actions.

### Simple Boolean Evaluation

```javascript theme={null}
// Returns true when price drops below $100
const priceElement = document.querySelector('.price');
const price = parseFloat(priceElement.textContent.replace('$', ''));
return price < 100;
```

### Data Extraction with Schema

When you provide a Zod schema, the evaluation function should return data matching that schema:

```javascript theme={null}
// Extract structured data
const product = {
  name: document.querySelector('h1').textContent,
  price: parseFloat(document.querySelector('.price').textContent.replace('$', '')),
  inStock: document.querySelector('.availability').textContent.includes('In Stock'),
  rating: parseFloat(document.querySelector('.rating').textContent),
};

return product;
```

With corresponding Zod schema:

```javascript theme={null}
z.object({
  name: z.string(),
  price: z.number(),
  inStock: z.boolean(),
  rating: z.number().min(0).max(5),
});
```

## Stagehand Scripts

For complex interactions requiring browser automation, use Stagehand scripts:

```javascript theme={null}
{
  "useStagehandScript": true,
  "stagehandScript": `
    await page.goto(url);
    await page.click('.load-more');
    await page.waitForSelector('.results');

    const results = await page.evaluate(() => {
      return Array.from(document.querySelectorAll('.item')).map(item => ({
        title: item.querySelector('.title').textContent,
        price: item.querySelector('.price').textContent
      }));
    });

    return results.length > 10;
  `
}
```

## Task Execution

### Manual Execution

Trigger a task immediately via API:

```bash theme={null}
POST /api/notifications/{id}/execute
```

### Scheduled Execution

Tasks run automatically based on their cron schedule:

```javascript theme={null}
{
  "schedule": {
    "cron": "0 9 * * *"  // Daily at 9 AM
  }
}
```

Common cron patterns:

* `*/5 * * * *` - Every 5 minutes
* `0 * * * *` - Every hour
* `0 0 * * *` - Daily at midnight
* `0 0 * * 1` - Weekly on Monday
* `0 0 1 * *` - Monthly on the 1st

## Execution Results

Each execution produces a result:

```javascript theme={null}
{
  "id": "result-123",
  "taskId": "task-456",
  "executedAt": "2024-01-01T12:00:00Z",
  "success": true,
  "data": {
    // Extracted data if schema provided
  },
  "error": null,
  "actionsTriggered": 2
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Reliable Selectors" icon="crosshairs">
    Use stable CSS selectors or data attributes that won't break with minor UI changes
  </Card>

  <Card title="Error Handling" icon="shield">
    Include try-catch blocks in evaluation functions to handle missing elements gracefully
  </Card>

  <Card title="Efficient Schedules" icon="clock">
    Balance monitoring frequency with API limits and resource usage
  </Card>

  <Card title="Test First" icon="flask">
    Test evaluation functions manually before scheduling
  </Card>
</CardGroup>

## Advanced Features

### Conditional Actions

Trigger different actions based on evaluation results:

```javascript theme={null}
const price = parseFloat(document.querySelector('.price').textContent.replace('$', ''));

if (price < 50) {
  return { level: 'urgent', price };
} else if (price < 100) {
  return { level: 'normal', price };
}

return false; // Don't trigger actions
```

### Multi-Page Monitoring

Monitor multiple pages with a single task using Stagehand:

```javascript theme={null}
const urls = ['https://example.com/product/1', 'https://example.com/product/2'];

const results = [];
for (const url of urls) {
  await page.goto(url);
  const price = await page.evaluate(() => {
    return document.querySelector('.price').textContent;
  });
  results.push({ url, price });
}

return results;
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Evaluation function returns undefined">
    Ensure your function explicitly returns a value. Use `return false` instead of no return
    statement.
  </Accordion>

  <Accordion title="Selectors not finding elements">
    The page might be dynamically loaded. Use Stagehand scripts with `waitForSelector` for dynamic
    content.
  </Accordion>

  <Accordion title="Task not executing on schedule">
    Check that the cron expression is valid and the task is active. Verify system time and timezone
    settings.
  </Accordion>
</AccordionGroup>
