From b6e65c1cfd9b7bf041fda1f15f249671fbf7bfc7 Mon Sep 17 00:00:00 2001 From: Michael Novak Date: Tue, 14 Oct 2025 09:51:51 +0200 Subject: [PATCH 1/3] feat: Document new synthetic default dataset item event --- .../actors/publishing/monetize/index.mdx | 2 +- .../publishing/monetize/pay_per_event.mdx | 41 +++++++++++++------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/index.mdx b/sources/platform/actors/publishing/monetize/index.mdx index 467f271c8..11a0a8fb9 100644 --- a/sources/platform/actors/publishing/monetize/index.mdx +++ b/sources/platform/actors/publishing/monetize/index.mdx @@ -38,7 +38,7 @@ The following table compares the two main pricing models available for monetizin | Marketing boost | Standard visibility | Standard visibility | Priority store placement | | Commission opportunities| Standard 20% | Standard 20% | Promotional 0% periods (until 01/11/2025) | | Custom event billing | Not available | Not available | ✅ Charge for any event | -| Per-result billing | Not available | ✅ Charge per dataset item | Optional (via event) | +| Per-result billing | Not available | ✅ Charge per dataset item | Optional (via event; automatic via `apify-actor-default-dataset-item`) | ## Setting up monetization diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 5d0bc1be7..7caa4c29f 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -108,7 +108,7 @@ async def charge_for_api_product_detail(): async def main(): await Actor.init() - + # API call, or any other logic that you want to charge for charge_result = await charge_for_api_product_detail() @@ -136,7 +136,7 @@ Use our [SDKs](/sdk) (JS and, Python or use [`apify actor charge`](/cli/docs/nex ### Use synthetic start event `apify-actor-start` -:::info Synthetic Actor recommended +:::info Synthetic Actor start event recommended We recommend using the synthetic Actor start event in PPE Actors. It benefits both you and your users. @@ -179,13 +179,28 @@ Your Actor might already have a start event defined, such as `actor-start` or an If you want to use the synthetic start event, remove the existing start event from your Actor and add the synthetic start event in Apify Console in the **Publication** tab. +### Use synthetic default dataset item event `apify-actor-default-dataset-item` + +::::info Automatic per-item charging + +The `apify-actor-default-dataset-item` synthetic event charges users for each item written to the run's default dataset. It lets you align PPE pricing with per-result use cases without adding charging code to your Actor. + +:::: + +#### How the synthetic default dataset item event works + +- Apify automatically charges this event whenever your Actor writes an item to the default dataset (for example, when using `Actor.pushData` without opening a named dataset). +- No code changes are required to charge this event. +- You can remove the event in Apify Console if you don't want automatic charging for default dataset items. If you remove it, default dataset writes will no longer be charged automatically. +- The event applies only to the default dataset of the run. Writes to other (non-default) datasets are not charged by this synthetic event. + ### Set memory limits Set memory limits using `minMemoryMbytes` and `maxMemoryMbytes` in your [`actor.json`](https://docs.apify.com/platform/actors/development/actor-definition/actor-json) file to control platform usage costs. ```json { - "actorSpecification": 1, + "actorSpecification": 1, "name": "name-of-my-scraper", "version": "0.0", "minMemoryMbytes": 512, @@ -213,7 +228,7 @@ import { Actor } from 'apify'; const processUrl = async (url) => { const response = await fetch(url); - + if (response.status === 404) { // Charge for the work done and return error item in one call await Actor.pushData({ @@ -221,7 +236,7 @@ const processUrl = async (url) => { error: "404", errorMessage: "Page not found" }, 'scraped-result'); - + return; } @@ -232,7 +247,7 @@ await Actor.init(); const input = await Actor.getInput(); const { urls } = input; - + for (const url of urls) { await processUrl(url); } @@ -251,7 +266,7 @@ import requests async def process_url(url): response = requests.get(url) - + if response.status_code == 404: # Charge for the work done and return error item in one call await Actor.push_data({ @@ -259,22 +274,22 @@ async def process_url(url): 'error': '404', 'errorMessage': 'Page not found' }, 'scraped-result') - + return # Rest of the process_url function async def main(): await Actor.init() - + input_data = await Actor.get_input() urls = input_data.get('urls', []) - + for url in urls: await process_url(url) - + # Rest of the Actor logic - + await Actor.exit() ``` @@ -294,7 +309,7 @@ However, we acknowledge that some events don't produce tangible results (such as Examples: - _`post` event_: Each charge adds one social media post to the dataset -- _`profile` event_: Each charge adds one user profile to the dataset +- _`profile` event_: Each charge adds one user profile to the dataset - _`processed-image` event_: Each charge adds one processed image to the dataset - _`ai-analysis` event_: Each charge processes one document through an AI workflow (no tangible output, but valuable processing) From 3ee3f1c68264525c42c3f3fd63438523bee65689 Mon Sep 17 00:00:00 2001 From: Michael Novak Date: Thu, 16 Oct 2025 10:46:30 +0200 Subject: [PATCH 2/3] minor doc fixes --- sources/platform/actors/publishing/monetize/index.mdx | 2 +- .../actors/publishing/monetize/pay_per_event.mdx | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/index.mdx b/sources/platform/actors/publishing/monetize/index.mdx index 11a0a8fb9..2abadeeb4 100644 --- a/sources/platform/actors/publishing/monetize/index.mdx +++ b/sources/platform/actors/publishing/monetize/index.mdx @@ -38,7 +38,7 @@ The following table compares the two main pricing models available for monetizin | Marketing boost | Standard visibility | Standard visibility | Priority store placement | | Commission opportunities| Standard 20% | Standard 20% | Promotional 0% periods (until 01/11/2025) | | Custom event billing | Not available | Not available | ✅ Charge for any event | -| Per-result billing | Not available | ✅ Charge per dataset item | Optional (via event; automatic via `apify-actor-default-dataset-item`) | +| Per-result billing | Not available | ✅ Charge per dataset item | Optional (via event; automatic via `apify-default-dataset-item`) | ## Setting up monetization diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 7caa4c29f..be2dd2f4b 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -179,17 +179,15 @@ Your Actor might already have a start event defined, such as `actor-start` or an If you want to use the synthetic start event, remove the existing start event from your Actor and add the synthetic start event in Apify Console in the **Publication** tab. -### Use synthetic default dataset item event `apify-actor-default-dataset-item` +### Use synthetic default dataset item event `apify-default-dataset-item` -::::info Automatic per-item charging +The `apify-default-dataset-item` synthetic event charges users for each item written to the run's default dataset. It lets you align PPE pricing with per-result use cases without adding charging code to your Actor. -The `apify-actor-default-dataset-item` synthetic event charges users for each item written to the run's default dataset. It lets you align PPE pricing with per-result use cases without adding charging code to your Actor. - -:::: +This event simplifies migration from rental or pay-per-result Actors to the pay-per-event (PPE) model. No code changes are required. #### How the synthetic default dataset item event works -- Apify automatically charges this event whenever your Actor writes an item to the default dataset (for example, when using `Actor.pushData` without opening a named dataset). +- Apify automatically charges this event whenever your Actor writes an item to the default dataset (for example, when using `Actor.pushData`). - No code changes are required to charge this event. - You can remove the event in Apify Console if you don't want automatic charging for default dataset items. If you remove it, default dataset writes will no longer be charged automatically. - The event applies only to the default dataset of the run. Writes to other (non-default) datasets are not charged by this synthetic event. From f7edd6b47a6e608feccbb928bce38555fea2486c Mon Sep 17 00:00:00 2001 From: Michael Novak Date: Fri, 24 Oct 2025 11:55:01 +0200 Subject: [PATCH 3/3] fix - migration does not apply to rentals --- sources/platform/actors/publishing/monetize/pay_per_event.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index be2dd2f4b..296cb1567 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -183,7 +183,7 @@ If you want to use the synthetic start event, remove the existing start event fr The `apify-default-dataset-item` synthetic event charges users for each item written to the run's default dataset. It lets you align PPE pricing with per-result use cases without adding charging code to your Actor. -This event simplifies migration from rental or pay-per-result Actors to the pay-per-event (PPE) model. No code changes are required. +This event simplifies migration from pay-per-result (PPR) Actors to the pay-per-event (PPE) model. No code changes are required. #### How the synthetic default dataset item event works