thomfoolery commited on
Commit
465a7e3
·
1 Parent(s): 2a37c5f

first attempt

Browse files
Files changed (47) hide show
  1. .gitignore +16 -0
  2. Dockerfile +29 -0
  3. app.py +24 -0
  4. chainlit.md +14 -0
  5. crawler.py +20 -0
  6. data/admin-graphql/index-links.md +0 -0
  7. data/admin-graphql/index.md +0 -0
  8. data/flow/projects/Fraud-protection-for-gift-order.json +87 -0
  9. data/scraped/_sitemap.json +59 -0
  10. data/scraped/clean/flow.txt +90 -0
  11. data/scraped/clean/flow_actions.txt +16 -0
  12. data/scraped/clean/flow_actions_build-config-ui.txt +264 -0
  13. data/scraped/clean/flow_actions_create.txt +180 -0
  14. data/scraped/clean/flow_actions_endpoints.txt +408 -0
  15. data/scraped/clean/flow_configure-complex-data-types.txt +133 -0
  16. data/scraped/clean/flow_migrate-legacy-extensions.txt +74 -0
  17. data/scraped/clean/flow_templates.txt +11 -0
  18. data/scraped/clean/flow_templates_create-a-template.txt +101 -0
  19. data/scraped/clean/flow_templates_reference.txt +149 -0
  20. data/scraped/clean/flow_track-lifecycle-events.txt +119 -0
  21. data/scraped/clean/flow_triggers.txt +12 -0
  22. data/scraped/clean/flow_triggers_create.txt +176 -0
  23. data/scraped/clean/flow_triggers_reference.txt +156 -0
  24. data/scraped/raw/flow.txt +112 -0
  25. data/scraped/raw/flow_actions.txt +16 -0
  26. data/scraped/raw/flow_actions_build-config-ui.txt +895 -0
  27. data/scraped/raw/flow_actions_create.txt +298 -0
  28. data/scraped/raw/flow_actions_endpoints.txt +667 -0
  29. data/scraped/raw/flow_configure-complex-data-types.txt +301 -0
  30. data/scraped/raw/flow_migrate-legacy-extensions.txt +76 -0
  31. data/scraped/raw/flow_templates.txt +12 -0
  32. data/scraped/raw/flow_templates_create-a-template.txt +209 -0
  33. data/scraped/raw/flow_templates_reference.txt +286 -0
  34. data/scraped/raw/flow_track-lifecycle-events.txt +120 -0
  35. data/scraped/raw/flow_triggers.txt +12 -0
  36. data/scraped/raw/flow_triggers_create.txt +272 -0
  37. data/scraped/raw/flow_triggers_reference.txt +310 -0
  38. data/scraped/raw/shopify_dev/_docs_apps_build_flow.txt +112 -0
  39. data/scraped/raw/shopify_dev/_docs_apps_build_flow_migrate-legacy-extensions.txt +76 -0
  40. data/scraped/raw/shopify_dev/_docs_apps_build_flow_templates.txt +12 -0
  41. data/scraped/raw/shopify_dev/_docs_apps_build_flow_track-lifecycle-events.txt +120 -0
  42. data/scraped/raw/shopify_dev/_docs_apps_build_flow_triggers.txt +12 -0
  43. pyproject.toml +25 -0
  44. rag_graph.py +120 -0
  45. scraper/__init__.py +3 -0
  46. scraper/async_crawler.py +205 -0
  47. uv.lock +0 -0
.gitignore ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+
3
+ # Python-generated files
4
+ __pycache__/
5
+ *.py[oc]
6
+ build/
7
+ dist/
8
+ wheels/
9
+ *.egg-info
10
+
11
+ # misc
12
+ .env
13
+ .venv
14
+ .lock
15
+ .chainlit/
16
+ /data/vectors/
Dockerfile ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Get a distribution that has uv already installed
2
+ FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
3
+
4
+ # Add user - this is the user that will run the app
5
+ # If you do not set user, the app will run as root (undesirable)
6
+ RUN useradd -m -u 1000 user
7
+ USER user
8
+
9
+ # Set the home directory and path
10
+ ENV HOME=/home/user \
11
+ PATH=/home/user/.local/bin:$PATH
12
+
13
+ ENV UVICORN_WS_PROTOCOL=websockets
14
+
15
+
16
+ # Set the working directory
17
+ WORKDIR $HOME/app
18
+
19
+ # Copy the app to the container
20
+ COPY --chown=user . $HOME/app
21
+
22
+ # Install the dependencies
23
+ RUN uv sync && uv add websockets
24
+
25
+ # Expose the port
26
+ EXPOSE 7860
27
+
28
+ # Run the app
29
+ CMD ["uv", "run", "chainlit", "run", "app.py", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import chainlit as cl
2
+ from qdrant_client import QdrantClient
3
+ from rag_graph import RagGraph
4
+
5
+ @cl.cache
6
+ def get_qdrant_client():
7
+ from qdrant_client import QdrantClient
8
+ return QdrantClient(path='data/vectors')
9
+
10
+ @cl.on_chat_start
11
+ async def on_chat_start():
12
+ qdrant_client = get_qdrant_client()
13
+ rag_graph = RagGraph(qdrant_client)
14
+ rag_graph.create_rag_graph()
15
+
16
+ cl.user_session.set("rag_graph", rag_graph)
17
+
18
+ @cl.on_message
19
+ async def on_message(question: cl.Message):
20
+ msg = cl.Message(content="")
21
+ await msg.send() # Initialize the message first
22
+
23
+ rag_graph = cl.user_session.get("rag_graph")
24
+ await rag_graph.stream(question.content, msg) # Update the message when streaming is complete
chainlit.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Welcome to Chainlit! 🚀🤖
2
+
3
+ Hi there, Developer! 👋 We're excited to have you on board. Chainlit is a powerful tool designed to help you prototype, debug and share applications built on top of LLMs.
4
+
5
+ ## Useful Links 🔗
6
+
7
+ - **Documentation:** Get started with our comprehensive [Chainlit Documentation](https://docs.chainlit.io) 📚
8
+ - **Discord Community:** Join our friendly [Chainlit Discord](https://discord.gg/k73SQ3FyUh) to ask questions, share your projects, and connect with other developers! 💬
9
+
10
+ We can't wait to see what you create with Chainlit! Happy coding! 💻😊
11
+
12
+ ## Welcome screen
13
+
14
+ To modify the welcome screen, edit the `chainlit.md` file at the root of your project. If you do not want a welcome screen, just leave this file empty.
crawler.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import logging
3
+ from scraper.async_crawler import AsyncCrawler
4
+
5
+ logging.basicConfig(
6
+ level=logging.INFO,
7
+ format='%(asctime)s - %(levelname)s - %(message)s'
8
+ )
9
+
10
+ async def main():
11
+ try:
12
+ start_url = "https://shopify.dev/docs/apps/build/flow"
13
+ crawler = AsyncCrawler(start_url)
14
+ await crawler.run()
15
+ except Exception as e:
16
+ logging.error(f"Crawler failed: {str(e)}")
17
+ raise
18
+
19
+ if __name__ == "__main__":
20
+ asyncio.run(main())
data/admin-graphql/index-links.md ADDED
The diff for this file is too large to render. See raw diff
 
data/admin-graphql/index.md ADDED
The diff for this file is too large to render. See raw diff
 
data/flow/projects/Fraud-protection-for-gift-order.json ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "f05032018172f8f0dbe0b75152de0622e23ce6b10b6821a203bc2ef19aecbc42": {
3
+ "__metadata": { "version": 0.1 },
4
+ "root": {
5
+ "steps": [
6
+ {
7
+ "step_id": "33bd9630-3d9c-11ef-a96f-2dc942027bf2",
8
+ "step_position": [900, 1100],
9
+ "config_field_values": [],
10
+ "task_id": "dca67f51-b1b3-4c3e-b3cb-c38f32edf26d",
11
+ "task_version": "1.0",
12
+ "task_type": "TRIGGER",
13
+ "description": null,
14
+ "note": null,
15
+ "name": null
16
+ },
17
+ {
18
+ "step_id": "3b3a3e40-3d9c-11ef-a96f-2dc942027bf2",
19
+ "step_position": [1260, 1080],
20
+ "config_field_values": [
21
+ { "config_field_id": "order_id", "value": "order.id" },
22
+ { "config_field_id": "reason", "value": "inventory" },
23
+ { "config_field_id": "email", "value": "false" },
24
+ { "config_field_id": "refund_items", "value": "false" },
25
+ { "config_field_id": "refund_shipping", "value": "false" },
26
+ { "config_field_id": "restock", "value": "true" }
27
+ ],
28
+ "task_id": "shopify::admin::cancel_order",
29
+ "task_version": "0.1",
30
+ "task_type": "ACTION",
31
+ "description": "Cancel the order with high potential of fraud order",
32
+ "note": null,
33
+ "name": null
34
+ },
35
+ {
36
+ "step_id": "5f723f10-3d9c-11ef-a96f-2dc942027bf2",
37
+ "step_position": [1620, 1080],
38
+ "config_field_values": [
39
+ { "config_field_id": "customer_id", "value": "order.customer.id" },
40
+ { "config_field_id": "tags", "value": "[\"fraud\"]" }
41
+ ],
42
+ "task_id": "shopify::admin::add_customer_tags",
43
+ "task_version": "0.1",
44
+ "task_type": "ACTION",
45
+ "description": "Add tag \"fraud\" to the customer. This tag can be used with other flows to block those customers.",
46
+ "note": null,
47
+ "name": null
48
+ },
49
+ {
50
+ "step_id": "e4e18440-e8a4-11ef-b3d8-7ffa6d7e8da1",
51
+ "step_position": [1980, 1080],
52
+ "config_field_values": [
53
+ { "config_field_id": "condition", "value": "" }
54
+ ],
55
+ "task_id": "shopify::flow::condition",
56
+ "task_version": "0.1",
57
+ "task_type": "CONDITION",
58
+ "description": null,
59
+ "note": null,
60
+ "name": null
61
+ }
62
+ ],
63
+ "links": [
64
+ {
65
+ "from_step_id": "33bd9630-3d9c-11ef-a96f-2dc942027bf2",
66
+ "from_port_id": "output",
67
+ "to_step_id": "3b3a3e40-3d9c-11ef-a96f-2dc942027bf2",
68
+ "to_port_id": "input"
69
+ },
70
+ {
71
+ "from_step_id": "3b3a3e40-3d9c-11ef-a96f-2dc942027bf2",
72
+ "from_port_id": "output",
73
+ "to_step_id": "5f723f10-3d9c-11ef-a96f-2dc942027bf2",
74
+ "to_port_id": "input"
75
+ },
76
+ {
77
+ "from_step_id": "5f723f10-3d9c-11ef-a96f-2dc942027bf2",
78
+ "from_port_id": "output",
79
+ "to_step_id": "e4e18440-e8a4-11ef-b3d8-7ffa6d7e8da1",
80
+ "to_port_id": "input"
81
+ }
82
+ ],
83
+ "patched_fields": [],
84
+ "workflow_name": "Fraud protection for gift order"
85
+ }
86
+ }
87
+ }
data/scraped/_sitemap.json ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "https://shopify.dev/docs/apps/build/flow.txt": [
3
+ "https://shopify.dev/docs/apps/build/flow/triggers",
4
+ "https://shopify.dev/docs/apps/build/flow/templates/create-a-template",
5
+ "https://shopify.dev/docs/apps/build/flow/migrate-legacy-extensions",
6
+ "https://shopify.dev/docs/apps/build/flow/track-lifecycle-events",
7
+ "https://shopify.dev/docs/apps/build/flow/templates",
8
+ "https://shopify.dev/docs/apps/build/flow/actions"
9
+ ],
10
+ "https://shopify.dev/docs/apps/build/flow/triggers.txt": [
11
+ "https://shopify.dev/docs/apps/build/flow/triggers/reference",
12
+ "https://shopify.dev/docs/apps/build/flow/triggers/create"
13
+ ],
14
+ "https://shopify.dev/docs/apps/build/flow/migrate-legacy-extensions.txt": [],
15
+ "https://shopify.dev/docs/apps/build/flow/templates/create-a-template.txt": [
16
+ "https://shopify.dev/docs/apps/build/flow/templates/reference"
17
+ ],
18
+ "https://shopify.dev/docs/apps/build/flow/track-lifecycle-events.txt": [
19
+ "https://shopify.dev/docs/apps/build/flow/triggers",
20
+ "https://shopify.dev/docs/apps/build/flow/actions",
21
+ "https://shopify.dev/docs/apps/build/flow/triggers/create",
22
+ "https://shopify.dev/docs/apps/build/flow"
23
+ ],
24
+ "https://shopify.dev/docs/apps/build/flow/templates.txt": [
25
+ "https://shopify.dev/docs/apps/build/flow/templates/create-a-template"
26
+ ],
27
+ "https://shopify.dev/docs/apps/build/flow/actions.txt": [
28
+ "https://shopify.dev/docs/apps/build/flow/configure-complex-data-types",
29
+ "https://shopify.dev/docs/apps/build/flow/actions/build-config-ui",
30
+ "https://shopify.dev/docs/apps/build/flow/actions/create"
31
+ ],
32
+ "https://shopify.dev/docs/apps/build/flow/triggers/reference.txt": [
33
+ "https://shopify.dev/docs/apps/build/flow/configure-complex-data-types",
34
+ "https://shopify.dev/docs/apps/build/flow/triggers/create"
35
+ ],
36
+ "https://shopify.dev/docs/apps/build/flow/triggers/create.txt": [
37
+ "https://shopify.dev/docs/apps/build/flow/actions",
38
+ "https://shopify.dev/docs/apps/build/flow/configure-complex-data-types",
39
+ "https://shopify.dev/docs/apps/build/flow/track-lifecycle-events",
40
+ "https://shopify.dev/docs/apps/build/flow"
41
+ ],
42
+ "https://shopify.dev/docs/apps/build/flow/configure-complex-data-types.txt": [],
43
+ "https://shopify.dev/docs/apps/build/flow/templates/reference.txt": [],
44
+ "https://shopify.dev/docs/apps/build/flow/actions/build-config-ui.txt": [
45
+ "https://shopify.dev/docs/apps/build/flow/actions"
46
+ ],
47
+ "https://shopify.dev/docs/apps/build/flow/actions/create.txt": [
48
+ "https://shopify.dev/docs/apps/build/flow/actions/endpoints",
49
+ "https://shopify.dev/docs/apps/build/flow/triggers",
50
+ "https://shopify.dev/docs/apps/build/flow/actions/build-config-ui",
51
+ "https://shopify.dev/docs/apps/build/flow/configure-complex-data-types",
52
+ "https://shopify.dev/docs/apps/build/flow/triggers/create",
53
+ "https://shopify.dev/docs/apps/build/flow/track-lifecycle-events"
54
+ ],
55
+ "https://shopify.dev/docs/apps/build/flow/actions/endpoints.txt": [
56
+ "https://shopify.dev/docs/apps/build/flow/actions",
57
+ "https://shopify.dev/docs/apps/build/flow/actions/build-config-ui"
58
+ ]
59
+ }
data/scraped/clean/flow.txt ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ [Shopify Flow](https://apps.shopify.com/flow) is an app that allows merchants to customize their store through automation. As a developer, you can integrate your app with the Flow platform through custom tasks, such as triggers and actions.
4
+
5
+ ![A workflow for a low stock notification displaying a trigger, condition, and action](/assets/apps/flow/example-workflow-inventory-quantity-changed.png)
6
+
7
+ This guide introduces you to the different extensions you can create, building a Flow trigger and action, and considerations when making changes to your extensions.
8
+
9
+ ## Why build for Flow
10
+
11
+ Building for Flow can help you to increase the value of your app by allowing merchants to automate their business processes. For example, suppose that you have a review app. After a review is created, merchants might want to send a notification (using email, Slack, or SMS), award loyalty points, and more. If you build the `Review created` trigger, Flow allows merchants to do any of those actions with your app. By integrating with Flow, you can:
12
+
13
+ - **Improve integrations between your app, Shopify, and other apps**: Any task you build can be used with the triggers and actions that Flow already provides, which immediately connects your app to thousands of new features.
14
+ - **Save development time**: Rather than building and maintaining direct integrations with many other apps, you can integrate with Flow and provide similar value to your merchants.
15
+ - **Improved visibility**: Merchants can discover your templates or tasks in Flow, even if they don't have your app installed. Additionally, when you integrate with Flow, you receive a **Works with Flow** badge on your listing in the Shopify App Store. Your app will also be listed in the [Flow app directory](https://apps.shopify.com/collections/connectors-for-shopify-flow).
16
+
17
+ ## What you can build
18
+
19
+ As a Partner you can build one or more tasks related to your app for your merchants to use. These merchants need to have both your app and Shopify Flow installed. Shopify Flow includes the following task types:
20
+
21
+ | Extension type | Description | Example |
22
+ |---|---|---|
23
+ | [Trigger](/docs/apps/build/flow/triggers) | An event that starts a workflow, and can be something that happens in a store or in an app. | A new order is created in a merchant's online store. |
24
+ | Condition | A rule that determines whether an action will be taken. As a developer you cannot create a condition task. | A condition is set to check whether the total amount paid for the order is over $200.00. |
25
+ | [Action](/docs/apps/build/flow/actions) | A task that's executed in a store or in an app when certain conditions are met. | If the total amount paid for the order is over $200.00, then a tag is added to the customer account that placed the order. |
26
+ | [Template](/docs/apps/build/flow/templates) | An example that demonstrates how your task works for a key use case. Templates are available through Flow's template library. | A workflow that sends an internal email when your trigger runs. |
27
+
28
+ ## Plans supported
29
+
30
+ Flow is an optional app that's available to Shopify merchants on any paid plan. Flow is widely adopted by Shopify merchants, especially those with stores on Shopify Plus.
31
+
32
+ Flow features [differ by plan](https://help.shopify.com/en/manual/shopify-flow). For apps, the primary difference is that if you have a [custom app](https://help.shopify.com/en/manual/apps/app-types/custom-apps), your Flow app extensions are available only to a [Shopify Plus](https://www.shopify.com/plus) store that has your app installed.
33
+
34
+ ## Templates
35
+
36
+ A template in Shopify Flow is an example workflow that can be copied into a merchant's shop. Templates help merchants automate a specific use case with minimal or no additional configuration. Flow's template library offers hundreds of templates with features to filter, browse, and search. You can [create a template](/docs/apps/build/flow/templates/create-a-template) for Shopify Flow that showcases your custom triggers and actions and help merchants do more.
37
+
38
+ ## Getting started
39
+
40
+ <div class="resource-card-grid">
41
+ <a class="resource-card" href="/docs/apps/build/flow/triggers" data-theme-mode="">
42
+ <div class="resource-card__indicator-container"><img
43
+ src="/assets/resource-cards/authentication"
44
+ data-alt-src="/assets/resource-cards/authentication-dark"
45
+ aria-hidden="true"
46
+ class="resource-card__icon themed-image"> <h3 class="resource-card__title">
47
+ Learn more about triggers
48
+ </h3>
49
+ <p class="resource-card__description">Connect your app to Shopify Flow so that your app can send an event that starts a workflow. </a>
50
+ </div>
51
+ <p> <a class="resource-card" href="/docs/apps/build/flow/actions" data-theme-mode="">
52
+ <div class="resource-card__indicator-container"><img
53
+ src="/assets/resource-cards/star"
54
+ data-alt-src="/assets/resource-cards/star-dark"
55
+ aria-hidden="true"
56
+ class="resource-card__icon themed-image"> <h3 class="resource-card__title">
57
+ Learn more about actions
58
+ </h3>
59
+ <p class="resource-card__description">Connect your app to Shopify Flow so that your app receives data when a workflow action runs. </a>
60
+ </div>
61
+ <p> <a class="resource-card" href="/docs/apps/build/flow/templates" data-theme-mode="">
62
+ <div class="resource-card__indicator-container"><img
63
+ src="/assets/resource-cards/filesystem"
64
+ data-alt-src="/assets/resource-cards/filesystem-dark"
65
+ aria-hidden="true"
66
+ class="resource-card__icon themed-image"> <h3 class="resource-card__title">
67
+ Learn more about Flow templates
68
+ </h3>
69
+ <p class="resource-card__description">Create workflow templates to showcase your triggers and actions. </a>
70
+ </div>
71
+ <p> <a class="resource-card" href="/docs/apps/build/flow/track-lifecycle-events" data-theme-mode="">
72
+ <div class="resource-card__indicator-container"><img
73
+ src="/assets/resource-cards/changelog"
74
+ data-alt-src="/assets/resource-cards/changelog-dark"
75
+ aria-hidden="true"
76
+ class="resource-card__icon themed-image"> <h3 class="resource-card__title">
77
+ Lifecycle events
78
+ </h3>
79
+ <p class="resource-card__description">Get notified about events related to your Flow triggers and actions. </a>
80
+ </div>
81
+ <p> <a class="resource-card" href="/docs/apps/build/flow/migrate-legacy-extensions" data-theme-mode="">
82
+ <div class="resource-card__indicator-container"><img
83
+ src="/assets/resource-cards/cli"
84
+ data-alt-src="/assets/resource-cards/cli-dark"
85
+ aria-hidden="true"
86
+ class="resource-card__icon themed-image"> <h3 class="resource-card__title">
87
+ Migrate legacy Flow extensions
88
+ </h3>
89
+ <p class="resource-card__description">Learn how to migrate your existing extensions from the Partner Dashboard to CLI-managed. </a>
90
+
data/scraped/clean/flow_actions.txt ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## How actions work
4
+
5
+ An action is a workflow component in Shopify Flow. It represents a task that's executed in a store or in an app when certain conditions are met. You can connect your app to Shopify Flow so that your app receives data when a workflow action runs.
6
+
7
+ This guide shows you how to add an action to your app so that merchants can use it in their workflows.
8
+
9
+ ![A diagram that show how third party actions interface with Flow ](/assets/apps/flow/action_diagram.png)
10
+
11
+ ## Next steps
12
+
13
+ - Follow our step by step guide on [how to create and test a Flow action](/docs/apps/build/flow/actions/create).
14
+ - Check out our action endpoint guide for more information on how to setup an [execution endpoint](/docs/apps/build/flow/actions/endpoints#flow-action-execution), a [custom configuration page preview endpoint](/docs/apps/build/flow/actions/endpoints#custom-configuration-page-preview) and [custom validation](/docs/apps/build/flow/actions/endpoints#custom-validation).
15
+ - Learn more about how to [return complex data](/docs/apps/build/flow/configure-complex-data-types) in a Flow action.
16
+ - Interested in building a custom configuration page? Follow this [guide](/docs/apps/build/flow/actions/build-config-ui) to learn more.
data/scraped/clean/flow_actions_build-config-ui.txt ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ To give merchants a more seamless action configuration experience, and to allow them to manage resources that are external to Shopify Flow, you can embed a page from your app in the Shopify Flow editor.
4
+
5
+ In your Shopify Flow action configuration, merchants see a preview with an image and text that's fetched from your [custom configuration page preview URL](/docs/apps/build/flow/actions/endpoints#custom-configuration-page-preview). Merchants can click the button to access the custom configuration page.
6
+
7
+ <figure class="figure"><img src="https://cdn.shopify.com/shopifycloud/shopify_dev/assets/apps/flow/ccp-preview-d0bce046a2f45d366041698ab3e42abbf3ebd3a191696e16acaecb7718da5afb.png" class="lazyload" alt="A custom configuration page preview with an "Edit Email" button." width="899" height="737"></figure>
8
+
9
+ Your custom configuration page is then displayed in a frame in the Shopify admin.
10
+
11
+ <figure class="figure"><img src="https://cdn.shopify.com/shopifycloud/shopify_dev/assets/apps/flow/ccp-app-bridge-a41ecd52945725531037786df500785ea47a89f16b7df392e19be619bd133f64.png" class="lazyload" alt="The custom configuration page is rendered with an App Bridge title bar." width="1253" height="756"></figure>
12
+
13
+ In this tutorial, you'll learn how to render a custom configuration page in Shopify Flow, customize the page frame, and access data relevant to your action in the custom configuration page context.
14
+
15
+ ## Requirements
16
+
17
+ - You've created a [Partner account](https://www.shopify.com/partners).
18
+ - You've [created an app](/docs/apps/build/scaffold-app).
19
+
20
+ ## Resources
21
+
22
+ To implement this feature, you'll use the following:
23
+
24
+ - [Shopify App Bridge](/docs/api/app-bridge)
25
+ - App Bridge components
26
+ - App Bridge actions specific to the custom configuration page
27
+
28
+ ## Implementing a custom configuration page
29
+
30
+ To build a custom configuration page, you'll [use Shopify App Bridge to render a page from your app page in Shopify Flow](#use-shopify-app-bridge-to-render-your-app-page).
31
+
32
+ From the context of the custom configuration page, you can then [access step and property information](#access-action-information) that you can use to display the appropriate information.
33
+
34
+ You can also [add additional buttons](#add-buttons-to-the-app-bridge-title-bar) to the App Bridge title bar, or [trigger a redirect to the previous page](#return-to-the-previous-page).
35
+
36
+ ## Use Shopify App Bridge to render your app page
37
+
38
+ > Note:
39
+ > The specifics of the Custom Configuration Page integration varies between Shopify App Bridge versions. Make sure you implement the integration specific to your Shopify App Bridge version.
40
+
41
+ To render your custom configuration page, you need to integrate Shopify App Bridge on the route that you want to render. To learn about setting up Shopify App Bridge, refer to one of the following pages:
42
+
43
+ - [Getting started with Shopify App Bridge](/docs/api/app-bridge/previous-versions/app-bridge-from-npm/app-setup)
44
+ - [Getting started with App Bridge React](/docs/api/app-bridge-library#react)
45
+
46
+ ### Access action information
47
+
48
+ In the context of the custom configuration page, Shopify Flow makes the following action information available:
49
+
50
+ - **A `step_reference` search parameter**: `step_reference` is a unique ID for the step within a workflow, and can be used to identify the resource that the merchant is requesting.
51
+ - **Property data**: Properties contains the extension fields data that make up your [action payload schema](/docs/apps/build/flow/actions/endpoints#request). The properties are passed as an object containing the properties as key-value pairs:
52
+
53
+
54
+
55
+
56
+ ```json
57
+ {
58
+ <property-name>: <property-value>
59
+ }
60
+ ```
61
+
62
+
63
+
64
+ ### Shopify App Bridge integration for versions 4.X.X and up
65
+
66
+ #### Register to the Custom Configuration Page's intent
67
+
68
+ To access property data with Shopify App Bridge version 4.X.X and up, you will need to use the `shopify.intents` API. The following example code allows you to register to the Custom Configuration Page's intent:
69
+
70
+ ```jsx
71
+ import { useAppBridge } from '@shopify/app-bridge-react'
72
+
73
+ const Application = () => {
74
+ const shopify = useAppBridge()
75
+ const [intent, setIntent] = useState({})
76
+
77
+ useEffect(() => {
78
+ const cleanup = shopify.intents.register((intent) => {
79
+ setIntent(intent)
80
+ })
81
+
82
+ return () => cleanup()
83
+ }, []);
84
+
85
+ return <>...</>
86
+ }
87
+ ```
88
+
89
+ The `intent` object will contain the following data:
90
+
91
+ | Field | Data Type | Description |
92
+ | ------- | --------- | ----------------------------------------------------------------------------------------------------- |
93
+ | action | `string` | The action that has been registered for. In the case of the Custom Configuration Page, it will always be set to `configure`. |
94
+ | type | `string` | A GID with the following structure: `gid://flow/stepReference/<step-reference>`. |
95
+ | data | `object` | An object that contains the `properties` data. |
96
+ | finish | `method` | A function that allows you to navigate to the previous page. |
97
+
98
+ The register method also returns a cleanup function, which you can use to unregister from the intent when your component is unmounting.
99
+
100
+ #### Return to the previous page
101
+
102
+ By default, the title bar of the custom configuration page includes an **Exit** button that the user can use to return to the previous page. You can choose to trigger a redirect to the previous page using the `intent.finish()` method:
103
+
104
+ ```jsx
105
+ <Button
106
+ primary
107
+ onClick={() => {
108
+ intent.finish()
109
+ }}
110
+ >
111
+ Go back to Flow
112
+ </Button>
113
+ ```
114
+
115
+ #### Add buttons to the App Bridge title bar
116
+
117
+ You can add more actions to the navigation bar by using the **[ui-title-bar](/docs/api/app-bridge-library/web-components/ui-title-bar)** element. Only primary and secondary actions are supported.
118
+
119
+ ```jsx
120
+ function Page() {
121
+ return <ui-title-bar>
122
+ <button variant="primary" onClick={() => console.log('Primary action')}>
123
+ Primary action
124
+ </button>
125
+ <button onClick={() => console.log('Secondary action')}>
126
+ Secondary action
127
+ </button>
128
+ </ui-title-bar>
129
+ }
130
+ ```
131
+
132
+ ### Shopify App Bridge integration for versions 3.X.X and down
133
+
134
+ #### Request property data
135
+
136
+ To access property data, you need to subscribe to `APP::APP_FRAME::PROPERTIES_EVENT`, and then request the properties by triggering the `APP::APP_FRAME::REQUEST_PROPERTIES` event. The following example code subscribes to the properties event and requests the action properties in React:
137
+
138
+ ```jsx
139
+ import { useAppBridge } from '@shopify/app-bridge-react'
140
+
141
+ const Application = () => {
142
+ const app = useAppBridge()
143
+ const [propertiesData, setPropertiesData] = useState({})
144
+
145
+ useEffect(() => {
146
+ const unsubscribeToPropertiesEvent = app.subscribe(
147
+ 'APP::APP_FRAME::PROPERTIES_EVENT',
148
+ payload => {
149
+ setPropertiesData(payload['properties'])
150
+ },
151
+ )
152
+
153
+ return unsubscribeToPropertiesEvent
154
+ }, [app])
155
+
156
+ useEffect(() => {
157
+ app.dispatch({
158
+ type: 'APP::APP_FRAME::REQUEST_PROPERTIES',
159
+ group: 'AppFrame',
160
+ })
161
+ }, [])
162
+
163
+ return (...)
164
+ }
165
+ ```
166
+
167
+ #### Return to the previous page
168
+
169
+ By default, the title bar of the custom configuration page includes an **Exit** button that the user can use to return to the previous page. This might be the Shopify Flow editor. However, you can choose to trigger a redirect to the previous page using `APP::APP_FRAME::NAVIGATE_BACK`:
170
+
171
+ ```jsx
172
+ app.dispatch({
173
+ type: 'APP::APP_FRAME::NAVIGATE_BACK',
174
+ group: 'AppFrame',
175
+ })
176
+
177
+ ```
178
+
179
+ #### Add buttons to the App Bridge title bar
180
+
181
+ You can add more actions to the App Bridge title bar in one of two ways:
182
+
183
+ - Using `@shopify/app-bridge`: Use the [`Button.create`](/docs/api/app-bridge/previous-versions/actions/button#create-a-button) initializer to create the buttons, then pass them to the [`Titlebar.create`](/docs/api/app-bridge/previous-versions/actions/titlebar#plain-javascript) initializer to set the buttons. You need to keep a reference to the Titlebar instance if you wish to do additional updates after the initialization.
184
+ - Using `@shopify/app-bridge-react`: Pass the primary and secondary actions to the [`TitleBar`](/docs/api/app-bridge/previous-versions/actions/titlebar#react) React component.
185
+
186
+ Only primary and secondary actions on the TitleBar are supported. Other App Bridge actions are ignored.
187
+
188
+ ```js
189
+ import { TitleBar, Button } from '@shopify/app-bridge/actions'
190
+
191
+ // create the buttons
192
+ const primaryBtn = Button.create(app, {
193
+ label: 'Button 1',
194
+ })
195
+ const secondaryBtn = Button.create(app, {
196
+ label: 'Button 2',
197
+ })
198
+
199
+ // add click handlers
200
+ primaryBtn.subscribe(Button.Action.CLICK, () => {
201
+ console.log('button 1 clicked')
202
+ })
203
+ secondaryBtn.subscribe(Button.Action.CLICK, () => {
204
+ console.log('button 2 clicked')
205
+ })
206
+
207
+ const titleBar = TitleBar.create(app, {
208
+ title: '',
209
+ buttons: {
210
+ primary: primaryBtn,
211
+ secondary: [secondaryBtn],
212
+ },
213
+ })
214
+
215
+ // update buttons after initialization
216
+ const newPrimary = Button.create(app, {
217
+ label: 'New button',
218
+ })
219
+ newPrimary.subscribe(Button.Action.CLICK, () => {
220
+ console.log('new primary button clicked')
221
+ })
222
+
223
+ titleBar.set({
224
+ buttons: {
225
+ primary: newPrimary,
226
+ secondary: [secondaryBtn],
227
+ },
228
+ })
229
+
230
+ ```
231
+ ```jsx
232
+ import { TitleBar } from '@shopify/app-bridge-react'
233
+
234
+ function Page() {
235
+ const buttons = {
236
+ primaryAction: {
237
+ content: 'Button 1',
238
+ onAction: () => {
239
+ console.log('button 1 clicked')
240
+ },
241
+ },
242
+ secondaryActions: [
243
+ {
244
+ content: 'Button 2',
245
+ onAction: () => {
246
+ console.log('button 2 clicked')
247
+ },
248
+ },
249
+ ],
250
+ }
251
+
252
+ return <TitleBar title="" {...buttons} />
253
+ }
254
+ ```
255
+
256
+ ## Next steps
257
+
258
+ - Add [custom configuration page preview URL](/docs/apps/build/flow/actions/endpoints#custom-configuration-page-preview) and [custom validation](/docs/apps/build/flow/actions/endpoints#custom-validation) endpoints to your app.
259
+
260
+ - Add your custom configuration page preview URL, custom configuration page URL, and custom validation URL to [your Shopify Flow action configuration](/docs/apps/build/flow/actions).
261
+
262
+ > Note:
263
+ > To add a custom configuration page to your action, you also need to add a custom validation endpoint.
264
+
data/scraped/clean/flow_actions_create.txt ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ To create an action that merchants can use in their workflows, you need to add the action to your app. The action needs to contain the following information:
4
+
5
+ - The fields that the merchant needs to complete when they add the action to their workflows
6
+ - The URL that Shopify Flow uses to send (POST) the contents (JSON payload) of the action to your app
7
+
8
+ You also need to configure your app to process the data from the POST request when it arrives and to send status codes back to Shopify Flow.
9
+
10
+ To enhance the merchant experience and more closely integrate external systems, you can also [build a custom configuration page](/docs/apps/build/flow/actions/build-config-ui). To improve the reliability of your action, you can add [custom validation](/docs/apps/build/flow/actions/endpoints#custom-validation) for action properties.
11
+
12
+ ## Requirements
13
+
14
+ - You have the following:
15
+ - A test web server that has access to the Internet, so that it can receive POST requests from Shopify Flow
16
+ - A test app that works with the test web server
17
+ - A development store that has [Shopify Flow](https://apps.shopify.com/flow) and the test app installed
18
+
19
+ ## Step 1: Create a Flow Action
20
+
21
+ To give your Flow action a meaningful name, use the following guidelines:
22
+
23
+ - Use a present-tense verb + object acted on format. For example, `Place auction bid`.
24
+ - Use sentence case.
25
+ - Don't use punctuation.
26
+ - Separate words using spaces.
27
+
28
+ ### Using Shopify CLI
29
+
30
+ Use the Shopify CLI to generate a new extension:
31
+
32
+ 1. Navigate to your app directory.
33
+ 2. Run the following command:
34
+
35
+ ```bash
36
+ #!/bin/bash
37
+ shopify app generate extension
38
+ ```
39
+
40
+ 3. Select the `Flow Action` as the type of extension.
41
+ 4. Provide a meaningful name for your extension.
42
+
43
+ After you've followed the prompts, Shopify CLI generates the extension’s file representation in your app's `/extensions` directory and gives you a success message. You can then go into your app's `/extensions` directory and start editing your new extension.
44
+
45
+ The file structure of your extension should look like the following:
46
+
47
+ ```
48
+ /place-auction-bid
49
+ shopify.extension.toml
50
+ ```
51
+
52
+ To learn more about the extensions file structure, refer to [App structure](/docs/apps/build/cli-for-apps/app-structure) and the documentation for your extension type.
53
+
54
+ ### Using the Partner Dashboard
55
+
56
+ 1. In your Partner Dashboard, click [Apps](https://partners.shopify.com/current/apps).
57
+ 2. Select the app that you want to add your Shopify Flow action to.
58
+ 3. Click **Extensions**, then click **Create** or **Create extension**.
59
+ 4. Under the **Flow** tab, click **Flow/Actions**.
60
+ 5. In the **Extension name** field, name your action, such as `Place auction bid`. This name is used only for internal purposes.
61
+ 6. Enter a title and description for the action. In the **Action Preview** area, you can see how the title and action display to merchants when they're choosing actions in Shopify Flow.
62
+ 7. Enter the URL for the action execution endpoint that you created. Shopify Flow sends the action's JSON payload to this endpoint when it's about to execute your action.
63
+
64
+ ## Step 2: Customize a Flow action configuration file
65
+
66
+ In this section you'll use the default action template and update it to be a functional extension example. Once you have generated a Flow extension using Shopify CLI, follow the instructions below:
67
+
68
+ 1. Change the description to `Place a bid on an auction`.
69
+ 2. Update the `extensions.runtime_url` to an endpoint where you can receive the runtime request.
70
+ 3. On the second `settings.fields` field, update the following values:
71
+ - `type` to `number_decimal`
72
+ - `key` to `amount`
73
+ - `name` to `Bid Amount`
74
+ - Add a `description` property and set it to `The amount of the bid`
75
+
76
+ ```bash
77
+ [[extensions]]
78
+ name = "Place Auction Bid"
79
+ type = "flow_action"
80
+ handle = "place-bid"
81
+ description = "Place a bid on an auction"
82
+ runtime_url = "https://your-server-domain/path/to/action/handler"
83
+
84
+ [settings]
85
+
86
+ [[settings.fields]]
87
+ type = "customer_reference"
88
+ required = true
89
+
90
+ [[settings.fields]]
91
+ type = "number_decimal"
92
+ key = "amount"
93
+ name = "Bid Amount"
94
+ description = "The amount of the bid"
95
+ required = true
96
+ ```
97
+
98
+ ## Step 3: Configure your web server
99
+
100
+ To build a Shopify Flow action, you need to add a service to your web server to listen for the JSON payload that Shopify Flow sends when the action runs.
101
+
102
+ Optionally, you can also add the following:
103
+
104
+ - An endpoint to validate actions
105
+ - A [custom configuration page](/docs/apps/build/flow/actions/build-config-ui), and an endpoint that lets merchants preview your custom configuration page
106
+
107
+ Add the following API endpoints to your server:
108
+
109
+ | Endpoint | Purpose |
110
+ | --- | --- |
111
+ | [Flow action execution](/docs/apps/flow/actions/endpoints#flow-action-execution) | The endpoint where the automation tool sends your action's payload. The payload contains data that you can use to execute the action in your app.|
112
+ | [Custom configuration page preview](/docs/apps/flow/actions/endpoints#custom-configuration-page-preview) | An endpoint that provides data about your [custom configuration page](/docs/apps/build/flow/actions/build-config-ui) to display in the automation tool. This endpoint is required if you want to use a custom configuration page.|
113
+ | [Custom validation](/docs/apps/flow/actions/endpoints#custom-validation) | An endpoint that validates the contents of merchant-configurable properties in an action payload when an action is saved. This endpoint is required if you want to use a custom configuration page.|
114
+
115
+ To learn more about the endpoint requirements for your server, refer to [Action endpoints](/docs/apps/build/flow/actions/endpoints).
116
+
117
+ To learn how to create a custom configuration page, refer to [Build a custom configuration page](/docs/apps/build/flow/actions/build-config-ui).
118
+
119
+ ## Step 4: Enable the draft version of your action
120
+
121
+ Running [`app dev`](/docs/api/shopify-cli/app/app-dev) allows changes made to local files to update the draft version of your Flow task extensions. The draft version is only available in your development store.
122
+
123
+ > Note:
124
+ > When [`app dev`](/docs/api/shopify-cli/app/app-dev) is running and "Development store preview" is enabled, the draft version of a task will appear in your development store _in place_ of the deployed version. Other shops will continue to see the deployed version of your task (if one exists). Draft versions can be identified by the "draft" badge. To see the deployed version of the task in your development store, turn off "Development store preview" in the "Extensions" section of your app in [Shopify Partners](https://partners.shopify.com/).
125
+
126
+ 1. Navigate to your app directory.
127
+ 2. Run the following command to start using draft versions of your extension(s):
128
+
129
+ ```bash
130
+ #!/bin/bash
131
+ shopify app dev
132
+ ```
133
+
134
+ 3. Follow the prompts.
135
+
136
+ ## Step 5: Test the action
137
+
138
+ After you've created an action in the Partner Dashboard and added support for it in your web server, you can test the action in Shopify Flow on your development store.
139
+
140
+ 1. In your development store, create a [workflow](https://www.shopify.com/admin/apps/flow) that uses the action. For example, add the trigger that you created in the [Triggers guide](/docs/apps/build/flow/triggers/create) and this action to a workflow.
141
+
142
+ 2. If you created a custom configuration page, then ensure that the preview displays and that the custom configuration page is accessible.
143
+
144
+ 3. If you added any custom validation, then ensure that it works as expected.
145
+
146
+ 4. Trigger the workflow. For example, in your web server, run the event that sends the trigger information to Shopify Flow.
147
+
148
+ When the workflow completes, your web server has sent data to Shopify Flow because of the trigger. Shopify Flow has sent this data to a web server that logged the information to its console because of the action.
149
+
150
+ ## Step 6: Deploy your extension
151
+
152
+ > Note:
153
+ > Deploying extensions using the `app deploy` command also publishes the extensions. We recommend testing changes by using [`app dev`](/docs/api/shopify-cli/app/app-dev) or deploying to a test app before deploying them to a production app.
154
+
155
+ Use Shopify CLI to deploy your extensions:
156
+
157
+ 1. Navigate to your app directory.
158
+ 2. Run the following command to start deploying your extension(s):
159
+
160
+ ```bash
161
+ #!/bin/bash
162
+ shopify app deploy
163
+ ```
164
+
165
+ 3. Follow the prompts.
166
+
167
+ When you receive confirmation that the deploy was successful, your extensions have been released.
168
+
169
+ ## Verifying requests
170
+
171
+ For security reasons, make sure that you verify the following elements in each request:
172
+
173
+ - The POST request's HMAC header (either `x-shopify-hmac-sha256` or `http-x-shopify-hmac-sha256`). The HMAC header should be verified before you process the payload. For more information, refer to [Verifying requests](/docs/apps/build/flow/actions/endpoints#verifying-requests).
174
+ - The payload `handle`. This ID should match the `handle` of the action that you created, and can be retrieved from the payload preview.
175
+
176
+ ## Next steps
177
+
178
+ - Connect your app to Shopify Flow so that events that occur in your app can [trigger workflows](/docs/apps/build/flow/triggers).
179
+ - Learn how to receive [lifecycle events from Shopify Flow](/docs/apps/build/flow/track-lifecycle-events) about the stores that are using your triggers in enabled workflows.
180
+ - Learn more about how to [return complex data](/docs/apps/build/flow/configure-complex-data-types) in a Flow action.
data/scraped/clean/flow_actions_endpoints.txt ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ Before your app can receive communication from Flow actions, you need to create one or more standardized API endpoints on your web server. Review the information for each endpoint to understand its requirements, the format of the payload, and the expected response. You'll also learn how to avoid processing duplicate requests, identify an action by its ID, and verify requests for security purposes.
4
+
5
+ | Endpoint | Purpose |
6
+ | --- | --- |
7
+ | [Flow action execution](/docs/apps/flow/actions/endpoints#flow-action-execution) | The endpoint where the automation tool sends your action's payload. The payload contains data that you can use to execute the action in your app.|
8
+ | [Custom configuration page preview](/docs/apps/flow/actions/endpoints#custom-configuration-page-preview) | An endpoint that provides data about your [custom configuration page](/docs/apps/build/flow/actions/build-config-ui) to display in the automation tool. This endpoint is required if you want to use a custom configuration page.|
9
+ | [Custom validation](/docs/apps/flow/actions/endpoints#custom-validation) | An endpoint that validates the contents of merchant-configurable properties in an action payload when an action is saved. This endpoint is required if you want to use a custom configuration page.|
10
+
11
+ ## General endpoint requirements
12
+
13
+ The requirements for Shopify Flow action endpoints are as follows:
14
+
15
+ | Rule / concern | Type / requirement |
16
+ | --- | --- |
17
+ | API format | REST |
18
+ | Content type | JSON |
19
+ | Security mechanism | [HMAC / Signed requests](#verifying-requests) |
20
+ | Protocol | HTTPS (app domain requires valid SSL certificate) |
21
+
22
+ ## Flow action execution
23
+
24
+ When a workflow that contains your action is executed, Flow sends an HTTP request to your Flow action execution endpoint (runtime URL). The request contains a payload that matches the payload schema that you configured for your action.
25
+
26
+ ### Request
27
+
28
+ <script data-option="filename" data-value="POST <Flow action HTTPS request URL>">```
29
+
30
+ ```json
31
+ {
32
+ "shop_id": "gid://shopify/Shop/1",
33
+ "shopify_domain": "{shop}.myshopify.com",
34
+ "action_run_id": "xxxx-xxxx-xxxx-xxxx",
35
+ "action_definition_id": "Place auction bid",
36
+ "handle": "place-auction-bid",
37
+ "properties": {
38
+ "customer_id": "123456",
39
+ "amount": "10.00",
40
+ "step_reference": "320d4f8a-aaab-40ff-9ed2-2bc079633705"
41
+ }
42
+ }
43
+ ```
44
+
45
+ The payload contains the following parameters:
46
+
47
+ | Property Name | Property Usage |
48
+ | ------------------- | ------------------------------------------------------------------------------------------------------ |
49
+ | `shop_id` | The ID of the store. |
50
+ | `shopify_domain` | The myshopify.com domain of the store. |
51
+ | `action_run_id` | An ID that represents an instance of an action being run. [Learn more](#prevent-apps-from-processing-duplicate-requests). |
52
+ | `handle` | The extension’s handle. We recommend using this property to identify your actions. |
53
+ | `step_reference` | A unique ID for the step within a workflow. This property only appears if you’ve set a [Custom Configuration Page](/docs/apps/build/flow/actions/build-config-ui). |
54
+ | `action_definition_id` | A unique ID for the action. The ID is based on the action name in the Partner Dashboard. | |
55
+ | `properties` | The fields that you selected as part of the action configuration. |
56
+
57
+ To learn how to configure the payload schema, refer to [Shopify Flow actions](/docs/apps/build/flow/actions).
58
+
59
+ ### Expected response
60
+
61
+ After the automation tool sends a POST request to your web server, it waits for a maximum of 10 seconds for an [HTTP status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes).
62
+
63
+ If after 10 seconds the automation tool hasn't received a response from your web server, then the automation tool closes the connection to your web server and resends the request later.
64
+
65
+ When the automation tool receives a response, it processes the codes as displayed in the following table:
66
+
67
+ <table>
68
+ <tr>
69
+ <th>Status codes</th>
70
+ <th>Description</th>
71
+ </tr>
72
+ <tr>
73
+ <td>200 Success</td>
74
+ <td>The automation tool assumes that the POST request has been processed by your web server.</td>
75
+ </tr>
76
+ <tr>
77
+ <td>202 Success</td>
78
+ <td>The automation tool assumes that the POST request has been accepted but not processed by your web server. The automation tool will resend the POST request at increasing intervals for up to 36 hours.
79
+ </td>
80
+ </tr>
81
+ <tr>
82
+ <td>4XX Client errors</td>
83
+ <td>
84
+ <p>If your web server sends a 429 status code without a <code>Retry-After</code> header, then the automation tool resends the POST request at increasing intervals for up to 36 hours. <p>If your web server sends a 429 status code with a <code>Retry-After</code> header that specifies a wait time, then the automation tool resends the POST request after the wait time (formatted in seconds) has passed. <p>If your web server sends any other 4XX code, then the automation tool assumes that there was a failure and it doesn't resend the POST request. Merchants see a notification in the automation tool that includes the raw contents of your web server's response. <p><strong>Example</strong>: <code>400 Bad Request { "error1": "server unresponsive" }</code> <p>You can provide a merchant-friendly description of the error by adding a key named <code>message</code>. For example: <p><strong>Example</strong>: <code>{ "message": "Finish the onboarding on our website." }</code>
85
+ </td>
86
+ </tr>
87
+ <tr>
88
+ <td>5XX Server errors</td>
89
+ <td>The automation tool resends the POST request at increasing intervals for up to 36 hours.</td>
90
+ </tr>
91
+ <tr>
92
+ <td>Other status code</td>
93
+ <td>If your web server returns a code that isn't described in this table, then the automation tool assumes that there was a failure and it doesn't resend the POST request.</td>
94
+ </tr>
95
+ </table>
96
+
97
+ ### Prevent apps from processing duplicate requests
98
+
99
+ Each request from an automation workflow contains an `action_run_id` that's unique to the associated action run. This ID is included in the body of the request.
100
+
101
+ You can use `action_run_id` as an [idempotency key](/docs/api/usage/idempotent-requests) to check if the request is unique. In some cases, your app could receive an identical request more than once. For example, the automation tool might resend a request because it didn't receive your response in time. Your app can store the idempotency key in a cache with a set expiry time to avoid reprocessing duplicate requests.
102
+
103
+ ### Identify actions
104
+
105
+ The `handle` property is how you identify the action for processing when your web server receives a request from Flow during workflow execution.
106
+
107
+ ```json
108
+ {
109
+ "shop_id": 0,
110
+ "shopify_domain": "{shop}.myshopify.com",
111
+ "action_run_id": "xxxx-xxxx-xxxx-xxxx",
112
+ "handle": "auction-bid",
113
+ "action_definition_id": "Auction Bid",
114
+ "properties": {}
115
+ }
116
+ ```
117
+
118
+ ## Custom configuration page preview
119
+
120
+ An endpoint that provides data about your [custom configuration page](/docs/apps/build/flow/actions/build-config-ui) to display in the automation tool. This endpoint is required if you want to use a custom configuration page. Using the endpoint, you can dynamically set the following information:
121
+
122
+ - The field’s label
123
+ - A text preview
124
+ - A last updated at timestamp
125
+ - An image preview
126
+ - The text used by the button that redirects to the custom configuration page
127
+
128
+ ### Request
129
+
130
+ <script data-option="filename" data-value="POST <Custom configuration page preview URL>">```
131
+
132
+ ```json
133
+ {
134
+ "shop_id": "gid://shopify/Shop/1",
135
+ "shopify_domain": "{shop}.myshopify.com",
136
+ "step_reference": "122438de2e57d8bad7e50958d2bd4999ca2c4c35ee3b5120e85e42a17fc1ce93",
137
+ "handle": "my-extension-handle",
138
+ "locale":"en",
139
+ "properties": {
140
+ "customer_id": "gid://shopify/Customer/1234567",
141
+ "sms_message": "Thanks for making the purchase!",
142
+ "marketing_activity_id": "gid://shopify/MarketingActivity/1234567"
143
+ }
144
+ }
145
+ ```
146
+
147
+ The payload contains the following parameters:
148
+
149
+ | Parameter | Description |
150
+ | ---------------------- | --- |
151
+ | `shop_id` | The ID of the store. |
152
+ | `shopify_domain` | The myshopify.com domain of the store. |
153
+ | `handle` | The extension’s handle. We recommend using this property to identify your actions. |
154
+ | `step_reference` | A unique ID for the step within a workflow. |
155
+ | `locale` | The locale of the store making the request, in ISO format. |
156
+ | `properties` | The fields that you selected as part of the action configuration. |
157
+
158
+ ### Expected response
159
+
160
+ ```json
161
+ {
162
+ "label_text": "Abandonment Email Template",
163
+ "text_preview": "We want you back. Enjoy a 15% discount on your next purchase.",
164
+ "button_text": "Edit Email",
165
+ "image_preview": {
166
+ "url": "http://someUrl.io/assets/preview_image.png",
167
+ "alt": "Abandonment Email Template Preview Image"
168
+ },
169
+ "last_updated_at": "2023-02-10T16:50:24.709Z"
170
+ }
171
+
172
+ ```
173
+
174
+ Other than `text_preview`, all fields are nullable.
175
+
176
+ <table>
177
+   <caption></caption>
178
+   <thead>
179
+     <tr>
180
+       <th scope=“col”>Parameter</th>
181
+       <th scope=“col”>Description</th>
182
+     </tr>
183
+   </thead>
184
+   <tbody>
185
+     <tr>
186
+ <td scope=“row”>1</td>
187
+       <td><code>label_text</code></td>
188
+       <td>A title for the custom configuration page.<br><br>If no value is specified, then the label text defaults to <b>Configuration Page Preview</b>.</td>
189
+     </tr>
190
+     <tr>
191
+ <td scope=“row”>2</td>
192
+       <td><code>text_preview</code></td>
193
+       <td>A preview that indicates the resource that's tied to the step. For example, in the case of an email content editor, this might be a preview of the email text.<br><br>This field is required.</td>
194
+     </tr>
195
+     <tr>
196
+ <td scope=“row”>3</td>
197
+       <td><code>button_text</code></td>
198
+       <td>The text for the button that the merchant clicks to access the custom configuration page.<br><br>If no value is specified, then the label text defaults to <b>Edit<b>.<br><br>If the value for `button_text` is longer than 23 characters, then the label is truncated to twenty characters with an ellipsis.</td>
199
+     </tr>
200
+     <tr>
201
+ <td scope=“row”></td>
202
+       <td><code>image_preview</code></td>
203
+       <td>The details of the image.</td>
204
+     </tr>
205
+     <tr>
206
+ <td scope=“row”>4</td>
207
+       <td><code>image_preview.url</code></td>
208
+       <td>The URL for a preview image of the custom configuration page. The image should be between 500px and 600px wide, and 100KB or less. There is no maximum height.</td>
209
+     </tr>
210
+     <tr>
211
+ <td scope=“row”></td>
212
+       <td><code>image_preview.thumbnail_url</code></td>
213
+       <td>The URL for a thumbnail version of the preview image.<br><br>This image is not currently used in the user interface.</td>
214
+     </tr>
215
+     <tr>
216
+ <td scope=“row”></td>
217
+       <td><code>image_preview.alt</code></td>
218
+       <td>The alt text for the preview image. This text appears if your image fails to render, and is accessible to screen readers.</td>
219
+     </tr>
220
+     <tr>
221
+ <td scope=“row”>5</td>
222
+       <td><code>last_updated_at</code></td>
223
+       <td>The date and time that the resource was last updated, in <a href="https://en.wikipedia.org/wiki/ISO_8601">IS0-8601</a> format.</td>
224
+     </tr>
225
+   </tbody>
226
+ </table>
227
+
228
+ <figure class="figure"><img src="https://cdn.shopify.com/shopifycloud/shopify_dev/assets/apps/flow/ccp-preview-annotated-379253a9b1eebe09194a0a0a0e5be1e2fd918fc977bdd1f78db60fa6f1e119c3.png" class="lazyload" alt="A labeled custom configuration page." width="901" height="675"></figure>
229
+
230
+ ## Custom validation
231
+
232
+ An endpoint that validates the contents of merchant-configurable properties in an action payload when an action is saved. This endpoint is required if you want to use a custom configuration page.
233
+
234
+ ### Request
235
+
236
+ The request contains a payload that matches the payload schema you configured for your action.
237
+
238
+ <script data-option="filename" data-value="POST <Validation endpoint>">```
239
+
240
+ ```json
241
+ {
242
+ "shop_id": "gid://shopify/Shop/1",
243
+ "shopify_domain": "{shop}.myshopify.com",
244
+ "handle": "my-extension-handle",
245
+ "locale": "en",
246
+ "steps": [
247
+ {
248
+ "step_reference": "122438de2e57d8bad7e50958d2bd4999ca2c4c35ee3b5120e85e42a17fc1ce93",
249
+ "properties" : {
250
+ "outside_na": true,
251
+ "guest_no": 22,
252
+ "first_name": "John",
253
+ "customer_id": "customer.id"
254
+ }
255
+ },
256
+ {
257
+ "step_reference": "ca2c4c35ee3b5120e85e42a17fc1ce93122438de2e57d8bad7e50958d2bd4999",
258
+ "properties" : {
259
+ "outside_na": false,
260
+ "guest_no": 14,
261
+ "first_name": "Kim",
262
+ "customer_id": "customer.id"
263
+ }
264
+ },
265
+ ]
266
+ }
267
+
268
+ ```
269
+
270
+ The payload contains the following parameters:
271
+
272
+ <table>
273
+   <caption></caption>
274
+   <thead>
275
+     <tr>
276
+       <th scope=“col”>Parameter</th>
277
+       <th scope=“col”>Description</th>
278
+     </tr>
279
+   </thead>
280
+   <tbody>
281
+     <tr>
282
+       <td scope=“row”><code>shop_id</code></td>
283
+       <td>The ID of the store.</td>
284
+     </tr>
285
+     <tr>
286
+       <td scope=“row”><code>shopify_domain</code></td>
287
+       <td>The myshopify.com domain of the store.</td>
288
+     </tr>
289
+     <tr>
290
+       <td scope=“row”><code>handle</code></td>
291
+       <td>The extension’s handle. We recommend using this property to identify your actions.</td>
292
+     </tr>
293
+     <tr>
294
+       <td scope=“row”><code>locale</code></td>
295
+       <td>The locale of the store, in ISO format.</td>
296
+     </tr>
297
+     <tr>
298
+       <td scope=“row”><code>steps</code></td>
299
+       <td>An array of all of the steps to validate. Each child step object represents a separate action on the merchant’s workflow.</td>
300
+     </tr>
301
+     <tr>
302
+       <td scope=“row”><code>steps.step_reference</code></td>
303
+       <td>The unique identifier for the step. This ID should be used when returning errors for a step.</td>
304
+     </tr>
305
+     <tr>
306
+       <td scope=“row”><code>steps.properties</code></td>
307
+       <td>
308
+ <p>An object containing the properties specified on the action. <p><b>Merchant-configurable properties</b>: These properties are passed as strings, with the following exceptions: <ul>
309
+ <li>Checkbox properties: Boolean</li>
310
+ <li>Number properties: integer</li>
311
+ </ul>
312
+ <p><b>Shopify properties</b>:
313
+ The path to the value for the related commerce object in the workflow environment. For example, <code>customer.id</code>. If the value isn't available in the workflow environment, then an empty string is returned. The property will be populated with an actual value at runtime. <p><b>Example 1: Customer ID is available in the workflow environment</b> <ul>
314
+ <li>Validation payload value: "customer.id"</li>
315
+ <li>Runtime value: "123456"</li>
316
+ </ul>
317
+ <p><b>Example 2: Customer ID isn't available in the workflow environment</b> <ul>
318
+ <li>Validation payload value: ""</li>
319
+ <li>Runtime value: null</li>
320
+ </ul>
321
+ <p>If a property is marked as optional, then the workflow tool won't validate the presence of the commerce object, and will only rely on external validation. The path to the value for the commerce objects is still returned as a path, but Shopify can't guarantee their presence at runtime. If you need a commerce object to be present at runtime, then you should mark it as required. This allows the workflow tool to assess the presence of the commerce object and return any errors to the editor. <p><b>Example 3: Customer ID might be available in the workflow environment (for example, when using a custom trigger and an order step)</b> <ul>
322
+ <li>Validation payload value: "customer.lastOrder.id"</li>
323
+ <li>Runtime value: "123456" OR null</li>
324
+ </ul>
325
+
326
+ </td>
327
+     </tr>
328
+   </tbody>
329
+ </table>
330
+
331
+ ### Expected response
332
+
333
+ Your app should return an array of the steps that you validated, which are identified by their `step_reference`. If there are any validation errors, then specify them in a `step_errors` array. The error messages that return display to the merchant in the action configuration pane in Shopify Flow.
334
+
335
+ ![An image of error messages in the action configuration pane.](/assets/apps/flow/validation-error.png)
336
+
337
+ ```yml
338
+ [
339
+ {
340
+ step_reference: '122438de2e57d8bad7e50958d2bd4999ca2c4c35ee3b5120e85e42a17fc1ce93',
341
+ step_errors: [
342
+ {
343
+ message: 'A step level error occurred'
344
+ }
345
+ ],
346
+ properties_errors: [
347
+ {
348
+ id: 'guest_no',
349
+ message: 'Number of guests is limited to 8 when outside of North America'
350
+ }
351
+ ]
352
+ },
353
+ {
354
+ step_reference: 'ca2c4c35ee3b5120e85e42a17fc1ce93122438de2e57d8bad7e50958d2bd4999',
355
+ step_errors: [],
356
+ properties_errors: []
357
+ }
358
+ ]
359
+ ```
360
+
361
+ <table>
362
+   <caption></caption>
363
+   <thead>
364
+     <tr>
365
+       <th scope=“col”>Parameter</th>
366
+       <th scope=“col”>Description</th>
367
+     </tr>
368
+   </thead>
369
+   <tbody>
370
+     <tr>
371
+       <td scope=“row”><code>step_reference</code></td>
372
+       <td>The unique identifier for the step. This ID should be used when returning errors for a step.</td>
373
+     </tr>
374
+     <tr>
375
+       <td scope=“row”><code>step_errors</code></td>
376
+       <td>An array of errors that apply to the entire step.</td>
377
+     </tr>
378
+     <tr>
379
+       <td scope=“row”><code>step_errors.message</code></td>
380
+       <td>An error message to display at the top of the action configuration pane.</td>
381
+     </tr>
382
+     <tr>
383
+       <td scope=“row”><code>properties_errors</code></td>
384
+       <td>An array of errors that apply to particular properties.</td>
385
+     </tr>
386
+     <tr>
387
+       <td scope=“row”><code>properties_errors.id</code></td>
388
+       <td>The key of the property that contains the error.</td>
389
+     </tr>
390
+     <tr>
391
+       <td scope=“row”><code>properties_errors.message</code></td>
392
+       <td>An error message to display for the property.</td>
393
+     </tr>
394
+   </tbody>
395
+ </table>
396
+
397
+ ## Verifying requests
398
+
399
+ For security reasons, your web service should enforce a hash-based message authentication (HMAC) header verification that uses the client secret that you created when you configured your app.
400
+
401
+ The name of the HMAC header is `x-shopify-hmac-sha256`. If you are using a Ruby-based web framework, then the name of the header is `http-x-shopify-hmac-sha256`.
402
+
403
+ When the action runs in a workflow, the automation tool posts the contents (JSON payload and the HMAC header) of the action to the URL that you entered when you created the action in the Partner Dashboard. When your web server receives the POST request, it needs to verify the HMAC header against the JSON payload and your app's API secret. The HMAC verification works the same as [webhooks](/docs/apps/build/webhooks/subscribe/https).
404
+
405
+ Your web server also needs to [verify that the `handle` that's sent in the payload matches the `handle` of the action that you created](#identify-actions).
406
+
407
+ After you've verified the HMAC header, you can process the contents of the payload. For example, you could log the contents of the payload to your web server's console.
408
+
data/scraped/clean/flow_configure-complex-data-types.txt ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ Triggers and actions can both provide data to Flow workflows. This data can be simple, such as a string or a number, or complex, such as an object or a list of objects. This guide explains how to define complex data types in your extension's TOML and how to send and receive complex data types at runtime.
4
+
5
+ ## Defining a return type schema
6
+
7
+ To return data from an action or complex objects from a trigger, you must provide a schema for the return type using GraphQL's type system ([SDL](https://graphql.org/learn/schema/#type-language)). This schema is used by Flow to provide the return object in the workflow editor. The schema can be defined in any file and linked to from your extension's TOML definition. For example, a file called `schema.graphql` which contains the SDL for the types used in your action or trigger, can be made in the same directory as the extension.
8
+
9
+ ### SDL file
10
+
11
+ When you're using complex types in Flow actions and triggers, consider the following:
12
+
13
+ - Flow supports defining types using basic types (String, Int, Float, Boolean, and ID) as well as enums, objects, lists, and the non-nullable flag `!`.
14
+ - Flow doesn't currently support the entire SDL spec when defining action return types. Unions, interfaces, custom scalars, and directives are currently not supported. The action HTTP payload doesn't utilize any arguments defined on types in this schema.
15
+ - Flow derives the description of the return value from the comment on the type, which is placed in double quotes above the field. This description displays to merchants in the Flow editor when selecting the field.
16
+ - The same schema file can be referenced by multiple extensions as long as the relative paths are defined correctly.
17
+
18
+ The following SDL defines two types: a `Bid` and an `Auction` which contains a list of bids. The schema can contain multiple types that reference each other but only one type can be defined as the return type for the action. In the following example we're referencing the `Bid` type in the `Auction` type.
19
+
20
+ ```graphql
21
+ "Represents a bid placed on an auction"
22
+ type Bid {
23
+ "ID of the bid"
24
+ id: ID!
25
+ "Customer that placed the bid"
26
+ customerId: ID!
27
+ "Amount of the bid"
28
+ amount: Float!
29
+ }
30
+
31
+ enum Status {
32
+ COMPLETE
33
+ IN_PROGRESS
34
+ CANCELLED
35
+ }
36
+
37
+ "Represents an auction"
38
+ type Auction {
39
+ "ID of the auction"
40
+ id: ID!
41
+ "Name of the auction"
42
+ name: String
43
+ "Status of the auction"
44
+ status: Status!
45
+ "List of bids placed on the auction"
46
+ bids: [Bid!]!
47
+ }
48
+ ```
49
+
50
+ For more information on SDL, refer to the [GraphQL documentation](https://graphql.org/learn/schema/#type-language).
51
+
52
+ ### Folder structure
53
+
54
+ ```
55
+ /my-extension-name
56
+ shopify.extensions.toml
57
+ schema.graphql
58
+ ```
59
+
60
+ ### `shopify.extension.toml` file
61
+
62
+ ```bash
63
+ [[extensions]]
64
+ name = "Place auction bid"
65
+ type = "flow_action"
66
+ handle = "auction-bid"
67
+ description = "My description"
68
+ runtime_url = "https://{url}.com/api/execute"
69
+ schema = "./schema.graphql"
70
+ return_type_ref = "Auction"
71
+ ```
72
+
73
+ ## Referencing the return type schema in an action extension's TOML
74
+
75
+ After a schema file has been defined, it can be referenced in the action extension's TOML by setting `extensions.schema` to the relative path of the schema file, and `extension.return_type_ref` to a type defined in the referenced schema file. The schema defined above can be referenced by setting the following fields:
76
+
77
+ | Property Name | Property value |
78
+ | ------------------- | --------------- |
79
+ | `extensions.schema` | ./schema.graphql |
80
+ | `extensions.return_type_ref` | Auction |
81
+
82
+ ## Referencing the return type schema in a trigger extension's TOML
83
+
84
+ After a schema file has been defined, it can be referenced in the trigger extension's TOML by setting `extensions.schema` to the relative path of the schema file, and setting the type of a field to `schema.<type>`. The schema defined above can be referenced by setting the following fields:
85
+
86
+ | Property Name | Property value |
87
+ | ------------------- | --------------- |
88
+ | `extensions.schema` | ./schema.graphql |
89
+ | `extensions.settings.fields[0].type` | schema.Auction |
90
+
91
+ ## Returning data from an action at runtime
92
+
93
+ When responding to an action request from Flow you can add the return type in the JSON response as a field called `return_value`. The `return_value` object must match the return type defined in the extension. The return type used in our [example](#shopify-extension-toml-file) must be an auction object, like the following:
94
+
95
+ ```json
96
+ {
97
+ "return_value": {
98
+ "id": "auction1",
99
+ "name": "My first auction",
100
+ "status": "COMPLETE",
101
+ "bids": [
102
+ {
103
+ "id": "bid1",
104
+ "customerId": "gid://shopify/Customer/1",
105
+ "amount": 100.00
106
+ },
107
+ {
108
+ "id": "bid2",
109
+ "customerId": "gid://shopify/Customer/2",
110
+ "amount": 103.11
111
+ }
112
+ ]
113
+ }
114
+ }
115
+ ```
116
+
117
+ If a workflow is using a non-nullable field that's defined in the extension `schema` but is missing from the payload or there's a type mismatch between fields, then the action transiently fails.
118
+
119
+ The response size of the action must also be less than `50KB` exceeding this limit will also result in a transient failure. Actions that transiently fail will be retried at increasing intervals for up to 24 hours.
120
+
121
+ ## Sending complex objects in a trigger at runtime
122
+
123
+ When you execute the [`flowTriggerReceive`](/docs/apps/build/flow/triggers/create#step-4-test-your-trigger) mutation with one or more complex object fields, the payload must include a JSON representation of the complex object(s) matching the schema. For example, if the trigger has a field with key `Winning Bid` of type `Bid`, then the payload should include the following structure:
124
+
125
+ ```json
126
+ "payload": {
127
+ "Winning Bid": {
128
+ "id": "bid1",
129
+ "customerId": "gid://shopify/Customer/1",
130
+ "amount": 100.00
131
+ }
132
+ }
133
+ ```
data/scraped/clean/flow_migrate-legacy-extensions.txt ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ If you have existing Flow extensions that were created through the Partner Dashboard, then you can import these extensions into your codebase. After you deploy the extensions that you’ve imported into Shopify CLI, Shopify CLI manages those extensions going forward.
4
+
5
+ > Note:
6
+ > Extensions that are migrated to Shopify CLI use the `handle` properties. The `handle` property is a unique string that identifies your extension and that's used when interacting with the Shopify Flow API. For more information, refer to the [triggers](/docs/apps/build/flow/triggers/create#step-4-test-your-trigger) and [actions](/docs/apps/build/flow/actions/endpoints#request) runtime payloads.
7
+
8
+ A `handle` property is created in the extension's TOML configuration file after running the import command. Note that you can't change the `handle` property of the extensions that are present in your app's codebase after you've run the `dev` or `deploy` commands.
9
+
10
+ ### Requirements
11
+
12
+ - Create a [Partner account](https://www.shopify.com/partners).
13
+ - [Scaffold an app that uses Shopify CLI v3.70.0 or higher](/docs/apps/build/scaffold-app), or [migrate your existing app](/docs/apps/build/cli-for-apps/migrate-to-latest-cli) so it's compatible with Shopify CLI v3.70.0 or higher.
14
+ - [Migrate a Partner Dashboard-managed app](/docs/apps/build/cli-for-apps/migrate-from-dashboard).
15
+
16
+ ## Step 1: Import your Flow task extension locally
17
+
18
+ > Note:
19
+ > The command in this procedure only generates the local file representation of your Partner Dashboard extensions. Running the `deploy` command migrates your extensions to CLI managed-extensions. You can only import extensions that have versions. The published version is imported, if one exists. Otherwise, the latest version is imported.
20
+
21
+ 1. Navigate to your app directory.
22
+ 1. To start importing your Flow extension, run the following command:
23
+
24
+ ```bash
25
+ #!/bin/bash
26
+ shopify app import-extensions
27
+ ```
28
+
29
+ 1. Select the `Flow Extensions` option.
30
+ 1. Select an extension from the list of extensions that are available to import.
31
+
32
+ After you’ve selected the extension to import, Shopify CLI automatically generates the file representation in your application’s `/extensions` directory and displays a success message.
33
+
34
+ You can then go into your application’s `/extensions` directory and start editing your extension. The file structure of your extension should look like the following:
35
+
36
+ ```text
37
+ /my-flow-extension
38
+ shopify.extension.toml
39
+ ```
40
+
41
+ To learn more about the extensions file structure, refer to [App structure](/docs/apps/build/cli-for-apps/app-structure) and the documentation for your extension type.
42
+
43
+ ### Available Flags
44
+
45
+ #### `client_id`
46
+
47
+ An application’s `client_id`. The ID enables you to target a specific application when running the import command.
48
+
49
+ ```bash
50
+ #!/bin/bash
51
+ shopify app import-extensions --client_id abc123
52
+ ```
53
+
54
+ ## Step 2: Migrate your extension
55
+
56
+ After you've imported the extension, you can migrate your extension by using Shopify CLI's `deploy` command.
57
+
58
+ > Note:
59
+ > Deploying extensions using the `app deploy` command also publishes the extensions. We recommend testing changes by using [`app dev`](/docs/api/shopify-cli/app/app-dev) or deploying to a test app before deploying them to a production app.
60
+
61
+ Use Shopify CLI to deploy your extensions:
62
+
63
+ 1. Navigate to your app directory.
64
+ 2. Run the following command to start deploying your extension(s):
65
+
66
+ ```bash
67
+ #!/bin/bash
68
+ shopify app deploy
69
+ ```
70
+
71
+ 3. Follow the prompts.
72
+
73
+ When you receive confirmation that the deploy was successful, your extensions have been released.
74
+
data/scraped/clean/flow_templates.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## How templates work
4
+
5
+ A template in Shopify Flow is an example workflow that can be copied into a merchant's shop. Templates help merchants automate a specific use case with minimal or no additional configuration. Flow's template library offers hundreds of templates with features to filter, browse, and search. You can [create a template](/docs/apps/build/flow/templates/create-a-template) for Shopify Flow that showcases your custom triggers and actions and help merchants do more.
6
+
7
+ ![Flow template library](/assets/apps/flow/flow-template-library.png)
8
+
9
+ ## Next steps
10
+ - Follow our step by step guide on [creating a Flow template](/docs/apps/build/flow/templates/create-a-template).
11
+ - Learn more about how localize your template, the approval process, and more in the [reference resource](/docs/apps/build/flow/templates/reference#approval-process)
data/scraped/clean/flow_templates_create-a-template.txt ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ A template in Shopify Flow is an example workflow that can be copied into a merchant's shop. Templates help merchants automate a specific use case with minimal or no additional configuration. Flow's template library offers hundreds of templates with features to filter, browse, and search. You can create a template for Shopify Flow that showcases your custom triggers and actions and help merchants do more.
3
+
4
+ To create a workflow template that merchants can add to their workflow list, you need to add a Flow template extension to your app.
5
+
6
+ ## Requirements
7
+
8
+ - A [development store](/docs/api/development-stores) that has [Shopify Flow](https://apps.shopify.com/flow) and your app installed.
9
+ - Your existing custom triggers and actions are connected to your instance of Shopify Flow.
10
+ - [Shopify CLI](/docs/apps/build/cli-for-apps) installed with a version of `3.49` or higher.
11
+
12
+ ## Step 1: Create a workflow
13
+
14
+ A workflow is the foundation of a Flow template.
15
+
16
+ 1. In your development store navigate to **Apps** > **Flow**.
17
+ 2. Click **Create workflow**.
18
+ 3. In the workflow editor, build a workflow that solves a merchant use case and showcases your custom trigger and or actions.
19
+ 4. Optional: Tailor your template to a wider audience by [localizing your custom step descriptions](/docs/apps/build/flow/templates/reference#step-descriptions).
20
+ 5. After you're satisfied with your workflow, [export the workflow](https://help.shopify.com/en/manual/shopify-flow/manage#export-a-workflow) and save the `.flow` file locally.
21
+
22
+ > Note:
23
+ > - Remove any shop specific test data or replace with placeholder values if the merchant needs to provide a value. For example using the placeholder `YOUR_TAG_NAME` in a location where the merchant needs to provide a shop specific tag.<br />
24
+ > - Don't edit `.flow` files directly. Only make changes within the Flow app and export the updated workflow.<br />
25
+ > - Test your workflow thoroughly, ensuring the trigger, condition(s), and action(s) used provide the intended result.
26
+
27
+ ## Step 2: Create a Flow template extension
28
+
29
+ Use the Shopify CLI to generate a new extension:
30
+
31
+ 1. Navigate to your app directory.
32
+ 2. Run the following command:
33
+
34
+ ```bash
35
+ #!/bin/bash
36
+ shopify app generate extension
37
+ ```
38
+
39
+ 3. Select the `Flow Template` as the type of extension.
40
+ 4. Provide a meaningful name for your extension.
41
+
42
+ The name that you provide displays in the Partners Dashboard. Follow these guidelines when choosing a name:
43
+
44
+ - Don't use punctuation.
45
+ - Separate words using spaces.
46
+
47
+ After you've followed the prompts, Shopify CLI generates the extension’s file representation in your app's `/extensions` directory and returns a success message. You can then go into your app's `/extensions` directory and start editing your new extension.
48
+
49
+ > Note:
50
+ > Each Flow template extension can contain only a single template. To deploy multiple templates, you will need to create an extension for each template.
51
+
52
+ The file structure of your extension should look like the following:
53
+
54
+ ```ssh
55
+ /your-extension-name
56
+ /locales
57
+ en.default.json
58
+ fr.json
59
+ shopify.extension.toml
60
+ template.flow
61
+ ```
62
+
63
+ To learn more about the extensions file structure, refer to our [app structure](/docs/apps/build/cli-for-apps/app-structure) documentation and the [documentation](/docs/apps/build/flow/templates/reference) for the Flow template extension type.
64
+
65
+ ## Step 3: Configure extension
66
+ Configure your template extension to include information describing it's function for merchants, and settings that control visibility.
67
+
68
+ 1. Update the [shopify.extension.toml configuration file](/docs/apps/build/flow/templates/reference#toml).
69
+ 2. Update and add any additional locales. [Localization reference](/docs/apps/build/flow/templates/reference#localization).
70
+ 3. Replace `template.flow` with the workflow [that you exported](/docs/apps/build/flow/templates/create-a-template#step-1-create-a-workflow).
71
+ 4. Be sure to update the filename to match your chosen file path in the `shopify.extension.toml` file. `template.flow` is the default.
72
+
73
+ ## Step 4: Preview extension
74
+
75
+ Preview your template extension to see how it will be displayed to merchants before deploying and requesting review.
76
+
77
+ 1. Run the following command in Shopify CLI:
78
+
79
+ ```bash
80
+ #!/bin/bash
81
+ shopify app dev
82
+ ```
83
+
84
+ 2. In your development store's Shopify admin, navigate to [`/flow/editor/templates/dev`](https://admin.shopify.com/apps/flow/editor/templates/dev). From here you can preview your workflow, template card, and custom step descriptions.
85
+ 3. Refer to our [approval criteria](/docs/apps/build/flow/templates/reference#approval-process) to ensure that your extension meets our requirements.
86
+
87
+ ## Step 5: Deploy extension
88
+
89
+ Use Shopify CLI to deploy your extension.
90
+
91
+ 1. Navigate to your app directory.
92
+ 2. Run the following command to start deploying your extension(s):
93
+
94
+ ```bash
95
+ #!/bin/bash
96
+ shopify app deploy
97
+ ```
98
+
99
+ 3. Follow the command prompts
100
+
101
+ When you receive confirmation that the deploy was successful, a new app version in your Partner Dashboard displays, where you can submit a request for review. After the request for review has been submitted and the [approval process](/docs/apps/build/flow/templates/reference#approval-process) is complete, you can release the new version from your Partner Dashboard and your templates will display in Flow's template library.
data/scraped/clean/flow_templates_reference.txt ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ This guide provides explanations of key topics for building and deploying a Flow template extension. This includes the TOML configuration file, localization, and the template approval process.
4
+
5
+ ## TOML
6
+
7
+ When you first create a new Flow template extensions through Shopify CLI, you get a basic version of the `shopify.extension.toml` file structure that looks like the following example:
8
+
9
+ ```toml
10
+ [[extensions]]
11
+ name = "t:name"
12
+ type = "flow_template"
13
+ handle = "example-name"
14
+ description = "t:description"
15
+
16
+ [extensions.template]
17
+
18
+ categories = ["orders", "risk"]
19
+
20
+ module = "./template.flow"
21
+
22
+ require_app = false
23
+
24
+ discoverable = true
25
+
26
+ enabled = true
27
+ ```
28
+
29
+ ### Flow template extension fields
30
+
31
+ | Property | Description | Rules |
32
+ | ------------- | ---------------------------------------------------------------------------------- | ----------------- |
33
+ | `name` <br><span class="heading-flag">Required</span> | The title of the template. This property is translatable and will use the value for the key `name` in the translation files. | |
34
+ | `type` <br><span class="heading-flag">Required</span> | The type of your extension. This should always be set to `flow_template` for Flow templates.| - Value must be `flow_template`. |
35
+ | `handle` <br><span class="heading-flag">Required</span> | A globally-unique identifier for your extension. This property can't be changed after you’ve run the [`app dev`](/docs/api/shopify-cli/app/app-dev) or [`deploy`](/docs/api/shopify-cli/app/app-deploy) command. | - Can't exceed 30 characters.<br /> - Must only contain alphanumeric characters and hyphens. |
36
+ | `description` <br><span class="heading-flag">Optional</span> | The description of your template's workflow. This property is translatable and will use the value for the key `description` in the translation files. | |
37
+ | `categories` <br><span class="heading-flag">Required</span> | The categories that best describe the function of your template. | - Must be an array containing only strings of valid categories. <br /> - Must choose at least one category. Max 2 recommended. <br /> - Valid categories are: `buyer_experience`, `customers`, `inventory_and_merch`, `loyalty`, `orders`, `promotions`, `risk`, `fulfillment`, `b2b`, `payment_reminders`, `custom_data`, and `error_monitoring`. |
38
+ | `module` <br><span class="heading-flag">Required</span> | The file path of the template workflow in the extension's folder. |
39
+ | `require_app` <br><span class="heading-flag">Optional</span> | Whether your template is visible only to merchants who have your app installed. | - Defaults to `false`. |
40
+ | `discoverable` <br><span class="heading-flag">Optional</span> | Whether your template should be displayed in the template browser. When `false`, the template is accessible only through a deep link. | - Defaults to `true`. |
41
+ | `enabled` <br><span class="heading-flag">Optional</span> | Whether you template should be published and made available after being approved. | - Defaults to `true`.
42
+
43
+ ## Localization
44
+
45
+ Localizing your template by providing translated text allows a wider audience to understand your template better and can increase adoption.
46
+
47
+ You can provide translations for the following fields:
48
+
49
+ - **`name`**: Title of the template.
50
+ - **`description`**: Description of the template and it's purpose.
51
+ - **`preInstallNote`**: (Optional): Instructions for merchants to complete before activating the workflow. This field should only be included if setup is required before the template can be turned on.
52
+ - [Custom step descriptions](#step-descriptions) added within the workflow.
53
+
54
+ ### Adding additional locales
55
+
56
+ Add new `.json` files prefixed with the locale, for example `es.json`.
57
+
58
+ Add `default` to one of the locales to make it the fallback if a merchant's locale isn't in the locales you have provided. Example: `en.default.json`.
59
+
60
+ ### Step descriptions
61
+
62
+ You can provide translated custom step descriptions by adding a translation key wrapped by curly braces in the step description field. For example, `{expressShippingCondition}`. Ensure there's no other characters before or after `{yourKey}`. After adding this to your workflow, you can update the translation files to include the step description.
63
+
64
+ The following is an example:
65
+
66
+ ![How to format localized step descriptions in the Flow editor](/assets/apps/flow/localized_step_descriptions_in_flow_editor.png)
67
+
68
+ ```json
69
+ {
70
+ "name": "My Awesome Template!",
71
+ "description": "A template that helps increase merchant productivity",
72
+ "preInstallNote": "You must disable automatic payment capture in the Shopify Admin before using this template",
73
+ "expressShippingCondition": "This step will check if the order uses express shipping"
74
+ }
75
+ ```
76
+
77
+ ## Approval process
78
+
79
+ Before submitting your template extension for approval ensure that it meets the following criteria:
80
+
81
+ ### Workflow
82
+
83
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-1">
84
+ <label class="marketing-checkbox-label" for="template-criteria-1">
85
+ <p style="margin-left:30px">Provides value/solves a problem. For example, notifying the merchant when a buyer makes 10 purchases and adds a `VIP` tag to the customer.</label>
86
+
87
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-2">
88
+ <label class="marketing-checkbox-label" for="template-criteria-2">
89
+ <p style="margin-left:30px">Does not already exist within the [template library](https://admin.shopify.com/apps/flow/web/editor/templates).</label>
90
+
91
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-3">
92
+ <label class="marketing-checkbox-label" for="template-criteria-3">
93
+ <p style="margin-left:30px">Isn't malicious in its execution.</label>
94
+
95
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-4">
96
+ <label class="marketing-checkbox-label" for="template-criteria-4">
97
+ <p style="margin-left:30px">Is complete in its configuration. Validation errors might exist in the workflow where fields are left blank for input unique to the merchant.</label>
98
+
99
+ ### TOML
100
+
101
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-5">
102
+ <label class="marketing-checkbox-label" for="template-criteria-5">
103
+ <p style="margin-left:30px">Titles should use the format, "\<Description of key action\> when \<description of trigger\>".</label>
104
+
105
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-6">
106
+ <label class="marketing-checkbox-label" for="template-criteria-6">
107
+ <p style="margin-left:30px">Includes all required fields.</label>
108
+
109
+ ### Localization
110
+
111
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-7">
112
+ <label class="marketing-checkbox-label" for="template-criteria-7">
113
+ <p style="margin-left:30px">Has correct spelling and grammar.</label>
114
+
115
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-8">
116
+ <label class="marketing-checkbox-label" for="template-criteria-8">
117
+ <p style="margin-left:30px">Has a default localization, for example <code>en.default.json</code>.</label>
118
+
119
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-9">
120
+ <label class="marketing-checkbox-label" for="template-criteria-9">
121
+ <p style="margin-left:30px">Has an English translation.</label>
122
+
123
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-10">
124
+ <label class="marketing-checkbox-label" for="template-criteria-10">
125
+ <p style="margin-left:30px">Include the <code>preInstallNote</code> field if setup is required before the template can be turned on. If no prior setup is needed, then remove the <code>preInstallNote</code> field from the localization files before submitting the template extension.</label>
126
+
127
+ ### Access
128
+
129
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-11">
130
+ <label class="marketing-checkbox-label" for="template-criteria-11">
131
+ <p style="margin-left:30px">Flow’s testing account, at flow-connector-testing.myshopify.com has access to any actions, triggers, or resources that are required to test the templates, including access to the app.</label>
132
+
133
+ ### Limitations
134
+
135
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-12">
136
+ <label class="marketing-checkbox-label" for="template-criteria-12">
137
+ <p style="margin-left:30px">A maximum of 25 templates can be submitted for each app.</label>
138
+
139
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-13">
140
+ <label class="marketing-checkbox-label" for="template-criteria-13">
141
+ <p style="margin-left:30px">Public apps must be listed in the [Shopify App Store](https://apps.shopify.com/) prior to submitting a template.</label>
142
+
143
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-14">
144
+ <label class="marketing-checkbox-label" for="template-criteria-14">
145
+ <p style="margin-left:30px">Don't edit the `.flow` file directly. Only change and export updated workflows using the Flow app.</label>
146
+
147
+ ### Submitting your extension for approval
148
+
149
+ After you're satisfied with your template extension, [`deploy`](/docs/api/shopify-cli/app/app-deploy) a new app version from Shopify CLI. The Flow team will review your templates within three business days. Template reviews don't block your app version from releasing, but template changes won't be reflected until the approval process is complete. If we require changes, then we'll reject the review and follow up through email with feedback.
data/scraped/clean/flow_track-lifecycle-events.txt ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ This guide explains how to configure your app to receive trigger lifecycle callbacks from Shopify Flow.
4
+
5
+ When [creating a trigger](/docs/apps/build/flow/triggers/create), configuring a lifecycle callback enables your app to receive notifications from Shopify Flow about stores using the trigger and communicate changes in workflow status (e.g., enabling or disabling a workflow) back to the app. This helps optimize app performance by ensuring that trigger-related operations are only performed for stores that actually need them.
6
+
7
+ Apps must be properly configured to respond to trigger lifecycle callbacks. When a merchant attempts to enable a workflow that uses the trigger, Shopify Flow sends a lifecycle callback to the app's web server. If it doesn't promptly receive a response or receives a response with an HTTP status code that isn't `2xx`, then the merchant can't enable the workflow and make use of the trigger.
8
+
9
+ > Note:
10
+ > Legacy trigger discovery webhook extensions created using the Partner Dashboard are deprecated and must [migrate to the CLI](docs/apps/build/flow/migrate-legacy-extensions) before they can be edited.
11
+
12
+ ## How trigger lifecycle callbacks work
13
+
14
+ Trigger lifecycle callbacks contain identifying information about the trigger and the store using it and indicate whether the trigger is being used. You can use this information to track the stores that are currently using your triggers and then send trigger requests to only those stores.
15
+
16
+ ### Properties
17
+
18
+ The trigger lifecycle callback (HTTP POST request) is formatted in JSON and it contains the following properties:
19
+
20
+ <table>
21
+ <tr>
22
+ <th>Property</th>
23
+ <th>Data type</th>
24
+ <th width="40%">Description</th>
25
+ <th>Example</th>
26
+ </tr>
27
+ <tr>
28
+ <td><code>flow_trigger_definition_id</code></td>
29
+ <td>String</td>
30
+ <td>The unique identifier for your Shopify Flow trigger.</td>
31
+ <td>Add row to spreadsheet</td>
32
+ </tr>
33
+ <tr>
34
+ <td><code>has_enabled_flow</code></td>
35
+ <td>Boolean</td>
36
+ <td>Whether the store has an enabled workflow that uses your trigger. Valid values:
37
+ <ul>
38
+ <li><code>true</code>: There is at least one workflow that is enabled and that uses your trigger.</li>
39
+ <li><code>false</code>: There are no enabled workflows that use your trigger.</li>
40
+ </ul>
41
+ </td>
42
+ <td>true</td>
43
+ </tr>
44
+ <tr>
45
+ <td><code>shop_id</code></td>
46
+ <td>Number</td>
47
+ <td>The unique identifier for the Shopify store.</td>
48
+ <td>690933842</td>
49
+ </tr>
50
+ <tr>
51
+ <td><code>shopify_domain</code></td>
52
+ <td>String</td>
53
+ <td>The myshopify domain of the Shopify store.</td>
54
+ <td>johnsapparel.myshopify.com</td>
55
+ </tr>
56
+ <tr>
57
+ <td><code>timestamp</code></td>
58
+ <td><a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a> date and timestamp</td>
59
+ <td>
60
+ <p>The time when the notification was created. Notifications with newer timestamps should take precedence. If you already have a timestamp in your datastore and you receive a newer timestamp, then overwrite this payload's information in your datastore. Conversely, if you receive a timestamp that is older than the information in your datastore, then ignore this payload. </td>
61
+ <td>2019-01-25T16:44:10.999Z</td>
62
+ </tr>
63
+ </table>
64
+
65
+ The following is an example body of a usage notification (HTTP POST) request:
66
+
67
+ ```json
68
+ {
69
+ "flow_trigger_definition_id": "Add row to spreadsheet",
70
+ "has_enabled_flow": false,
71
+ "shop_id": "690933842",
72
+ "shopify_domain": "johnapparel.myshopify.com",
73
+ "timestamp": "2019-01-25T16:44:10.999Z"
74
+ }
75
+ ```
76
+
77
+ ### Callback events
78
+
79
+ Shopify Flow sends trigger lifecycle callbacks when the following events occur:
80
+
81
+ - When a merchant activates a workflow that uses your trigger, the callback contains `"has_enabled_flow": true`.
82
+ - When a merchant deactivates a workflow that uses your trigger, the callback contains `"has_enabled_flow": false`.
83
+
84
+ ### Web server response time and status codes
85
+
86
+ When a merchant tries to enable a workflow that uses your trigger, Shopify Flow sends a trigger lifecycle callback to your web server. If your web server doesn't respond within five seconds, or if it responds with a different status code, then the merchant can't enable that workflow. The merchant receives a notification in the Shopify Flow app that tells them to try enabling the workflow at a later time.
87
+
88
+ ## 1. Configure your web server
89
+
90
+ To begin, configure your web server to listen for Shopify Flow callbacks.
91
+
92
+ 1. Configure a URL in your web server to listen for the trigger lifecycle callbacks from Shopify Flow.
93
+ 2. Configure your web server to verify the HMAC header in the trigger lifecycle callback with your client secret.
94
+
95
+ The HMAC header is located in the following HTTP header: `x-shopify-hmac-sha256`. If you are using a Ruby-based web framework, then the header is `http-x-shopify-hmac-sha256`.
96
+
97
+ 3. Configure your web server to respond within 5 seconds when it receives a trigger lifecycle callback.
98
+
99
+ ## 2. Process and store callback data
100
+
101
+ After you've added support to listen for Shopify Flow callbacks, you can configure your web server to process and store the callback data.
102
+
103
+ 1. Save the list of stores that are using your triggers in a persistent datastore. Use the <code>timestamp</code> property to make sure that you don't overwrite an existing entry with older information.
104
+ 2. Edit your application to send your triggers only to stores that are using your triggers.
105
+
106
+ ## 3. Configure the callback
107
+
108
+ Finally, configure the callback in the CLI:
109
+
110
+ 1. Run `shopify app generate extension`.
111
+ 2. Select `Flow trigger lifecycle callback`.
112
+ 3. Change the URL in the generated TOML to the URL configured on the web server.
113
+ 4. Run `shopify app deploy`.
114
+
115
+ ## Next steps
116
+
117
+ - Familiarize yourself with [Shopify Flow](/docs/apps/build/flow) and learn about building connectors.
118
+ - Connect your app to Shopify Flow so that events that occur in your app can [trigger workflows](/docs/apps/build/flow/triggers).
119
+ - Connect your app to Shopify Flow so that your app receives data and information when a [workflow action](/docs/apps/build/flow/actions) runs.
data/scraped/clean/flow_triggers.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## How triggers work
4
+
5
+ A trigger is a task in Shopify Flow that starts the execution of a workflow. The trigger represents an event that happens in a store or in an app. You can [build a trigger](/docs/apps/build/flow/triggers/create) for Shopify Flow so that events in your app trigger workflows to run.
6
+
7
+ ![A diagram that show how third party triggers interface with Flow ](/assets/apps/flow/trigger_diagram.png)
8
+
9
+ ## Next steps
10
+
11
+ - To build a trigger, you need to [create a trigger extension](/docs/apps/build/flow/triggers/create) in your app. In that extension, you specify details about the trigger using a [TOML file](/docs/apps/build/flow/triggers/reference).
12
+ - Once you have published your extension, you can then test or use it by [calling the Shopify API](/docs/apps/build/flow/triggers/reference#mutation-api-reference) with the trigger payload.
data/scraped/clean/flow_triggers_create.txt ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## Requirements
4
+
5
+ Make sure that you have the following:
6
+
7
+ - A test web server that you can use to send information to Shopify Flow. You can use an existing web server. This web server needs to be able to send POST requests to Shopify's [GraphQL Admin API](/docs/api/admin-graphql).
8
+ - A test app that works with the test web server and can send HTTP requests.
9
+ - A development store that has [Shopify Flow](https://apps.shopify.com/flow) and the test app installed.
10
+ - Your application has access to the `read_customers` scope. The trigger you will build using this tutorial will be using a customer reference which requires that scope.
11
+
12
+ ## Step 1: Create a Flow trigger extension
13
+
14
+ To give your Flow action a meaningful name, use the following guidelines:
15
+
16
+ - Use an object acted on + past tense verb format. For example, `Auction bid placed`.
17
+ - Use sentence case.
18
+ - Don't use punctuation.
19
+ - Separate words using spaces.
20
+
21
+ ### Using Shopify CLI
22
+
23
+ The following steps show how to create a trigger that sends bid information to Shopify Flow when a bid is placed on an auction.
24
+
25
+ Use the Shopify CLI to generate a new extension:
26
+
27
+ 1. Navigate to your app directory.
28
+ 2. Run the following command:
29
+
30
+ ```bash
31
+ #!/bin/bash
32
+ shopify app generate extension
33
+ ```
34
+
35
+ 3. Select the `Flow Trigger` as the type of extension.
36
+ 4. Provide a meaningful name for your extension.
37
+
38
+ After you've followed the prompts, Shopify CLI generates the extension’s file representation in your app's `/extensions` directory and gives you a success message. You can then go into your app's `/extensions` directory and start editing your new extension.
39
+
40
+ The file structure of your extension should look like the following:
41
+
42
+ ```
43
+ /auction-bid-placed
44
+ shopify.extension.toml
45
+ ```
46
+
47
+ To learn more about the extensions file structure, refer to [App structure](/docs/apps/build/cli-for-apps/app-structure) and the documentation for your extension type.
48
+
49
+ ### Using the Partner Dashboard
50
+
51
+ 1. Open your [Partner Dashboard](https://partners.shopify.com).
52
+ 2. Click the app that you want to add your Shopify Flow trigger to.
53
+ 3. Click **Extensions**, then click **Create** or **Create extension**.
54
+ 4. Under **Flow**, click the **Flow/Triggers** card.
55
+ 5. Enter an internal extension name for your trigger and click **Save**.
56
+ 6. Enter a title and description for the trigger that will be shown to merchants.
57
+ 7. Copy the GraphQL endpoint that displays under the **Trigger description** field to a text file. Your app uses this endpoint to send your POST request to Shopify Flow. The endpoint follows the format `https://{shop}.myshopify.com/admin/api/latest/graphql.json`.
58
+ 8. In the **Request body properties** section, click **Add property**, choose a data type, and create the properties that display in Shopify Flow when a merchant chooses your trigger.
59
+
60
+ ## Step 2: Customize a Flow trigger configuration file
61
+
62
+ The following procedure requires you to have generated a flow extension using Shopify CLI. In this section you'll use the default trigger template and update it to be a functional extension example.
63
+
64
+ 1. Change description to `Trigger for auction bids.`
65
+ 2. On the second `[[settings.fields]]` field, update:
66
+ - `type` to `number_decimal`
67
+ - `key` to `Amount`
68
+
69
+ ```bash
70
+ [[extensions]]
71
+ name = "Auction Bid Placed"
72
+ type = "flow_trigger"
73
+ handle = "auction-bid-placed"
74
+ description = "Trigger for auction bids."
75
+
76
+ [settings]
77
+
78
+ [[settings.fields]]
79
+ type = "customer_reference"
80
+
81
+ [[settings.fields]]
82
+ type = "number_decimal"
83
+ key = "Amount"
84
+ ```
85
+
86
+ ## Step 3: Enable the draft version of your trigger
87
+
88
+ Running [`app dev`](/docs/api/shopify-cli/app/app-dev) allows changes made to local files to update the draft version of your Flow task extensions. The draft version is only available in your development store.
89
+
90
+ > Note:
91
+ > When [`app dev`](/docs/api/shopify-cli/app/app-dev) is running and "Development store preview" is enabled, the draft version of a task will appear in your development store _in place_ of the deployed version. Other shops will continue to see the deployed version of your task (if one exists). Draft versions can be identified by the "draft" badge. To see the deployed version of the task in your development store, turn off "Development store preview" in the "Extensions" section of your app in [Shopify Partners](https://partners.shopify.com/).
92
+
93
+ 1. Navigate to your app directory.
94
+ 2. Run the following command to start using draft versions of your extension(s):
95
+
96
+ ```bash
97
+ #!/bin/bash
98
+ shopify app dev
99
+ ```
100
+
101
+ 3. Follow the prompts.
102
+
103
+ ## Step 4: Test your trigger
104
+
105
+ After the [`app dev`](/docs/api/shopify-cli/app/app-dev) command has started, you can test the draft version of your trigger in Shopify Flow.
106
+
107
+ 1. In your development store, create a [workflow](https://www.shopify.com/admin/apps/flow) that uses the trigger that you created for your app.
108
+
109
+ 2. Using the Admin GraphQL API, send a `flowTriggerReceive` mutation with the following arguments:
110
+
111
+ - The `handle` of the trigger
112
+ - The `payload` of the trigger containing the fields defined in the extension TOML
113
+ - The size of the payload (keys included) must be under 50 KB. If the size of the properties body exceeds the limit, then Shopify responds to the GraphQL request with a validation error reading `Properties size exceeds the limit of 50000 bytes`. As a result, workflows with the specified trigger won't start from this request.
114
+
115
+ The following is an example of a `flowTriggerReceive` mutation:
116
+
117
+ ```graphql
118
+ mutation
119
+ {
120
+ flowTriggerReceive(
121
+ handle: "auction-bid-placed",
122
+ payload: {
123
+ "Amount": "30",
124
+ "customer_id": 12345
125
+ })
126
+ {
127
+ userErrors {field, message}
128
+ }
129
+ }
130
+ ```
131
+
132
+ > [Learn how to authenticate your GraphQL Admin API requests](/docs/api/admin-graphql#authentication).
133
+
134
+ The following example shows the same mutation sent in a curl request:
135
+
136
+ ```curl
137
+ curl --location 'https://{shop_domain}.myshopify.com/admin/api/latest/graphql.json' \
138
+ --header 'X-Shopify-Access-Token: {access_token}' \
139
+ --header 'Content-Type: application/json' \
140
+ --data '{
141
+ "query": "mutation flowTriggerReceive($handle: String, $payload: JSON) { flowTriggerReceive(handle: $handle, payload: $payload) { userErrors { message field } } }",
142
+ "variables": {
143
+ "handle": "auction-bid-placed",
144
+ "payload": {
145
+ "customer_id": {customer_id},
146
+ "Amount": 30
147
+ }
148
+ }
149
+ }'
150
+ ```
151
+
152
+ ## Step 5: Deploy your extension
153
+
154
+ > Note:
155
+ > Deploying extensions using the `app deploy` command also publishes the extensions. We recommend testing changes by using [`app dev`](/docs/api/shopify-cli/app/app-dev) or deploying to a test app before deploying them to a production app.
156
+
157
+ Use Shopify CLI to deploy your extensions:
158
+
159
+ 1. Navigate to your app directory.
160
+ 2. Run the following command to start deploying your extension(s):
161
+
162
+ ```bash
163
+ #!/bin/bash
164
+ shopify app deploy
165
+ ```
166
+
167
+ 3. Follow the prompts.
168
+
169
+ When you receive confirmation that the deploy was successful, your extensions have been released.
170
+
171
+ ## Next steps
172
+
173
+ - Familiarize yourself with [Shopify Flow](/docs/apps/build/flow) and learn about building connectors.
174
+ - Connect your app to Shopify Flow so that your app receives data and information when a [workflow action](/docs/apps/build/flow/actions) runs.
175
+ - Learn how to receive [lifecycle events from Shopify Flow](/docs/apps/build/flow/track-lifecycle-events) about the stores that are using your triggers in enabled workflows.
176
+ - Learn how to use [complex data types](/docs/apps/build/flow/configure-complex-data-types) in your Shopify Flow trigger.
data/scraped/clean/flow_triggers_reference.txt ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ When you create a new trigger extension using Shopify CLI, a basic version of the TOML configuration file structure is generated. In this guide, you'll learn about configuring the different sections and properties of the configuration file, including extension properties, extension fields, reference field types, custom field types, and more.
4
+
5
+ This guide will also inform you how to make HTTP requests to Flow to start the workflows in which your extension is the trigger.
6
+
7
+ ## TOML
8
+
9
+ > Note:
10
+ > Creating Flow extensions using Shopify CLI is an exciting new feature that is currently in development. As with any developing feature, it's important to note that the Flow's CLI capabilities will continue to evolve and improve over time. Developers can expect additional functionality, enhancements, and improvements to be added as development progresses.
11
+ >
12
+ >To create Flow extensions using [Shopify CLI](https://www.npmjs.com/package/@shopify/cli), ensure you have the latest version installed.
13
+
14
+ When you create a new trigger extension using Shopify CLI, you'll get a basic version of the TOML configuration file structure which should look like the following example:
15
+
16
+ ```bash
17
+ [[extensions]]
18
+ name = "Auction Bid"
19
+ type = "flow_trigger"
20
+ handle = "auction-bid"
21
+ description = "Your description"
22
+
23
+ [settings]
24
+
25
+ [[settings.fields]]
26
+ type = "customer_reference"
27
+
28
+ [[settings.fields]]
29
+ type = "single_line_text_field"
30
+ key = "your field key"
31
+ ```
32
+
33
+ ### Trigger extension properties
34
+
35
+ Extension properties are listed in the `[[extensions]]` section and enable you to define the interface between Flow and your event.
36
+
37
+ | Property name | Description | Rules |
38
+ | --------------------------- | ------------------------------------------------------------- | -------------------------------------- |
39
+ | `name` <br><span class="heading-flag">Required</span> | Name of your extension. Will be the merchant-facing name of your task in the editor. This should be something that is human readable. | |
40
+ | `type` <br><span class="heading-flag">Required</span> | The type of your extension. This should always be set to “flow_trigger” for Flow triggers. | - Value must be `flow_trigger`.
41
+ | `handle` <br><span class="heading-flag">Required</span> | A unique identifier for your extension. This property cannot be changed once you’ve run the `dev` or `deploy` command. | - Cannot exceed 30 characters.<br /> - Must be unique across your app's extensions. <br /> - Must only contain alphanumeric characters and hyphens. |
42
+ | `description` <br><span class="heading-flag">Optional</span> | A description of your extension. This description will be shown in the Flow editor navigation panel. | |
43
+
44
+ ### Trigger extension fields
45
+
46
+ Trigger extension fields are listed in the `[settings]` section, with each field using a `[[settings.field]]` header. These fields define the payload your event will send to Flow. You can add more than one field to your Flow trigger. The order of the fields in the TOML file is preserved when they're being rendered in the editor configuration panel. When sending a trigger payload, all fields defined in a trigger are required.
47
+
48
+ | Property name | Description | Rules |
49
+ | ------------------------------ | --------------------------------------------------------------------------------------------------- | --------------------------------|
50
+ | `type` <br><span class="heading-flag">Required</span> | The field type. | - [Accepted custom field types](#custom-field-types).<br> - [Accepted reference field types](#reference-field-types). |
51
+ | `key` <br><span class="heading-flag">Optional</span> | A unique key that identifies your field. This should be human readable since it will appear in the Flow editor in the environment picker menu. | - Required for custom field types. <br /> Should only contain alphabetic values or spaces. <br /> - This property is not valid for reference field types. |
52
+ | `description` <br><span class="heading-flag">Required</span> | A description of the field. This will appear in the Flow editor configuration panel. |
53
+
54
+ ### Supported field types
55
+
56
+ When you create a trigger, you add the fields that your trigger sends to Shopify Flow in the `[settings]` section of the TOML file. These fields define what your event plans to send to Shopify Flow. Merchants can then use that data in their conditions and actions.
57
+
58
+ You can add two types of fields: custom fields or predefined reference fields.
59
+
60
+ ![A diagram that shows how trigger properties are rendered in the Flow editor](/assets/apps/flow/trigger_properties_in_flow_editor.png)
61
+
62
+ ### Reference field types
63
+
64
+ A reference field lets you send the identifier of a Shopify resource to Shopify Flow. This allows merchants to build workflows that use any data related to that resource.
65
+
66
+ For example, your trigger sends a customer ID to Shopify Flow. The merchant can create a condition that checks `customer / amountSpent` and `customer / tags`. In their action, the merchant can include the template variables for customers, such as `{{customer.email}}`.
67
+
68
+ To specify that a trigger will include a reference field, you only need to specify the `type` and an optional `description` property. For example:
69
+
70
+ ```bash
71
+ ...
72
+
73
+ [settings]
74
+
75
+ [[settings.fields]]
76
+ type = "customer_reference"
77
+ ```
78
+
79
+ You can use the following reference fields:
80
+
81
+ | Reference type (TOML) | Payload key | Description |
82
+ | --- | --- | --- |
83
+ | `customer_reference` | `customer_id` | The [`id`](/docs/api/admin-rest/current/resources/customer#resource-object) or [`legacyResourceId`](/docs/api/admin-graphql/current/objects/customer#field-customer-legacyresourceid) of the customer.<br><br>Triggers that include this property in the request body are also available to [Shopify marketing automations](/docs/apps/build/marketing-analytics/automations). |
84
+ | `order_reference` | `order_id` | The [`id`](/docs/api/admin-rest/current/resources/order#resource-object) or [`legacyResourceId`](/docs/api/admin-graphql/current/objects/order#field-order-legacyresourceid) of the order. |
85
+ | `product_reference` | `product_id` | The [`id`](/docs/api/admin-rest/current/resources/product#resource-object) or [`legacyResourceId`](/docs/api/admin-graphql/current/objects/product#field-product-legacyresourceid) of the product. |
86
+
87
+ When making a request to Flow, include the payload key. See the [mutation API reference section](#mutation-api-reference) for a complete example.
88
+
89
+ ### Custom field
90
+
91
+ A custom field lets you define the data that you send as part of your trigger request. The following is an example:
92
+
93
+ ```bash
94
+ ...
95
+
96
+ [settings]
97
+
98
+ [[settings.fields]]
99
+ type = "number_decimal"
100
+ key = "Amount"
101
+ ```
102
+
103
+ #### Custom field types
104
+
105
+ The following are the available custom field types:
106
+
107
+ | Field type | Description | Example |
108
+ | ----------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------- |
109
+ | `boolean` | A Boolean value. | `true`, `false` |
110
+ | `email` | An email formatted string. | `"[email protected]"` |
111
+ | `single_line_text_field` | A string. | `"Hello world."`
112
+ | `number_decimal` | A number with a decimal point. | `1.0` |
113
+ | `url` | A URL formatted string. | `"https://example/com"` |
114
+ | `schema.<type>` | `<type>` can be any type defined in the provided schema. [Learn more about defining complex types](/docs/apps/build/flow/configure-complex-data-types). | `{ "foo": "bar", "baz": 123 }` |
115
+
116
+ #### Naming custom fields
117
+
118
+ Field names need to be self-describing and readable. Use sentence case and separate words with spaces (not underscores or hyphens). These names can contain only alphabetical characters (a-z, A-Z) and spaces.
119
+
120
+ When you refer to these fields in the payload that you send to Shopify Flow, enter the names verbatim . For example, `{ "City location": "Ottawa" } }`. Don't use shortened versions.
121
+
122
+ #### Custom fields in the Shopify Flow editor
123
+
124
+ Fields can be used in the Shopify Flow editor either in conditions or in actions as [template variables](https://help.shopify.com/manual/shopify-plus/flow2/reference/variables). When used as template variables, Shopify Flow converts your `key` property to camelCase such as `{{ customerEmail }}`.
125
+
126
+ ## Mutation API reference
127
+
128
+ Once your extension is defined, published, and activated in a workflow according to [this guide](/docs/apps/build/flow/triggers/create), you can call Flow's mutation with an event, which will start the workflow(s).
129
+
130
+ ```graphql
131
+ mutation
132
+ {
133
+ flowTriggerReceive(
134
+ handle: "auction-bid-placed",
135
+ payload: {
136
+ "Amount": "30",
137
+ "customer_id": 12345
138
+ })
139
+ {
140
+ userErrors {field, message}
141
+ }
142
+ }
143
+ ```
144
+
145
+ | Property name | Property usage |
146
+ | ------------------- | ------------------------------------------------------------------------------------------------------ |
147
+ | `handle` | The extension’s handle. |
148
+ | `payload` | The fields that you selected for your payload schema in the action configuration. These should be serialized in a key-value pair format where the keys are equal to your field's “key” properties. |
149
+
150
+ > Note:
151
+ > If you are using a Shopify admin API version of `2023-07` or earlier the mutation won't support the `handle` and `payload` properties. For information on that mutation shape you can rely on the [flowTriggerReceive documentation](/docs/api/admin-graphql/2023-07/mutations/flowTriggerReceive).
152
+
153
+ ## Considerations
154
+
155
+ - When you create a trigger, the payload that you send to Shopify Flow needs to be [less than 1 MB and contain specific content](/docs/apps/build/flow/triggers/create#step-4-test-your-trigger) in the body.
156
+ - Triggers have the same [API rate limits](/docs/api/usage/rate-limits) as the Shopify API.
data/scraped/raw/flow.txt ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ [Shopify Flow](https://apps.shopify.com/flow) is an app that allows merchants to customize their store through automation. As a developer, you can integrate your app with the Flow platform through custom tasks, such as triggers and actions.
4
+
5
+ ![A workflow for a low stock notification displaying a trigger, condition, and action](/assets/apps/flow/example-workflow-inventory-quantity-changed.png)
6
+
7
+ This guide introduces you to the different extensions you can create, building a Flow trigger and action, and considerations when making changes to your extensions.
8
+
9
+ ## Why build for Flow
10
+
11
+ Building for Flow can help you to increase the value of your app by allowing merchants to automate their business processes. For example, suppose that you have a review app. After a review is created, merchants might want to send a notification (using email, Slack, or SMS), award loyalty points, and more. If you build the `Review created` trigger, Flow allows merchants to do any of those actions with your app. By integrating with Flow, you can:
12
+
13
+ - **Improve integrations between your app, Shopify, and other apps**: Any task you build can be used with the triggers and actions that Flow already provides, which immediately connects your app to thousands of new features.
14
+ - **Save development time**: Rather than building and maintaining direct integrations with many other apps, you can integrate with Flow and provide similar value to your merchants.
15
+ - **Improved visibility**: Merchants can discover your templates or tasks in Flow, even if they don't have your app installed. Additionally, when you integrate with Flow, you receive a **Works with Flow** badge on your listing in the Shopify App Store. Your app will also be listed in the [Flow app directory](https://apps.shopify.com/collections/connectors-for-shopify-flow).
16
+
17
+ ## What you can build
18
+
19
+ As a Partner you can build one or more tasks related to your app for your merchants to use. These merchants need to have both your app and Shopify Flow installed. Shopify Flow includes the following task types:
20
+
21
+ | Extension type | Description | Example |
22
+ |---|---|---|
23
+ | [Trigger](/docs/apps/build/flow/triggers) | An event that starts a workflow, and can be something that happens in a store or in an app. | A new order is created in a merchant's online store. |
24
+ | Condition | A rule that determines whether an action will be taken. As a developer you cannot create a condition task. | A condition is set to check whether the total amount paid for the order is over $200.00. |
25
+ | [Action](/docs/apps/build/flow/actions) | A task that's executed in a store or in an app when certain conditions are met. | If the total amount paid for the order is over $200.00, then a tag is added to the customer account that placed the order. |
26
+ | [Template](/docs/apps/build/flow/templates) | An example that demonstrates how your task works for a key use case. Templates are available through Flow's template library. | A workflow that sends an internal email when your trigger runs. |
27
+
28
+ ## Plans supported
29
+
30
+ Flow is an optional app that's available to Shopify merchants on any paid plan. Flow is widely adopted by Shopify merchants, especially those with stores on Shopify Plus.
31
+
32
+ Flow features [differ by plan](https://help.shopify.com/en/manual/shopify-flow). For apps, the primary difference is that if you have a [custom app](https://help.shopify.com/en/manual/apps/app-types/custom-apps), your Flow app extensions are available only to a [Shopify Plus](https://www.shopify.com/plus) store that has your app installed.
33
+
34
+ ## Templates
35
+
36
+ A template in Shopify Flow is an example workflow that can be copied into a merchant's shop. Templates help merchants automate a specific use case with minimal or no additional configuration. Flow's template library offers hundreds of templates with features to filter, browse, and search. You can [create a template](/docs/apps/build/flow/templates/create-a-template) for Shopify Flow that showcases your custom triggers and actions and help merchants do more.
37
+
38
+
39
+ ## Getting started
40
+
41
+ <div class="resource-card-grid">
42
+ <div>
43
+ <a class="resource-card" href="/docs/apps/build/flow/triggers" data-theme-mode="">
44
+ <div class="resource-card__indicator-container"><img
45
+ src="/assets/resource-cards/authentication"
46
+ data-alt-src="/assets/resource-cards/authentication-dark"
47
+ aria-hidden="true"
48
+ class="resource-card__icon themed-image"></div>
49
+ <h3 class="resource-card__title">
50
+ Learn more about triggers
51
+ </h3>
52
+ <p class="resource-card__description">Connect your app to Shopify Flow so that your app can send an event that starts a workflow.</p>
53
+ </a>
54
+ </div></p>
55
+
56
+ <p><div>
57
+ <a class="resource-card" href="/docs/apps/build/flow/actions" data-theme-mode="">
58
+ <div class="resource-card__indicator-container"><img
59
+ src="/assets/resource-cards/star"
60
+ data-alt-src="/assets/resource-cards/star-dark"
61
+ aria-hidden="true"
62
+ class="resource-card__icon themed-image"></div>
63
+ <h3 class="resource-card__title">
64
+ Learn more about actions
65
+ </h3>
66
+ <p class="resource-card__description">Connect your app to Shopify Flow so that your app receives data when a workflow action runs.</p>
67
+ </a>
68
+ </div></p>
69
+
70
+ <p><div>
71
+ <a class="resource-card" href="/docs/apps/build/flow/templates" data-theme-mode="">
72
+ <div class="resource-card__indicator-container"><img
73
+ src="/assets/resource-cards/filesystem"
74
+ data-alt-src="/assets/resource-cards/filesystem-dark"
75
+ aria-hidden="true"
76
+ class="resource-card__icon themed-image"></div>
77
+ <h3 class="resource-card__title">
78
+ Learn more about Flow templates
79
+ </h3>
80
+ <p class="resource-card__description">Create workflow templates to showcase your triggers and actions.</p>
81
+ </a>
82
+ </div></p>
83
+
84
+ <p><div>
85
+ <a class="resource-card" href="/docs/apps/build/flow/track-lifecycle-events" data-theme-mode="">
86
+ <div class="resource-card__indicator-container"><img
87
+ src="/assets/resource-cards/changelog"
88
+ data-alt-src="/assets/resource-cards/changelog-dark"
89
+ aria-hidden="true"
90
+ class="resource-card__icon themed-image"></div>
91
+ <h3 class="resource-card__title">
92
+ Lifecycle events
93
+ </h3>
94
+ <p class="resource-card__description">Get notified about events related to your Flow triggers and actions.</p>
95
+ </a>
96
+ </div></p>
97
+
98
+ <p><div>
99
+ <a class="resource-card" href="/docs/apps/build/flow/migrate-legacy-extensions" data-theme-mode="">
100
+ <div class="resource-card__indicator-container"><img
101
+ src="/assets/resource-cards/cli"
102
+ data-alt-src="/assets/resource-cards/cli-dark"
103
+ aria-hidden="true"
104
+ class="resource-card__icon themed-image"></div>
105
+ <h3 class="resource-card__title">
106
+ Migrate legacy Flow extensions
107
+ </h3>
108
+ <p class="resource-card__description">Learn how to migrate your existing extensions from the Partner Dashboard to CLI-managed.</p>
109
+ </a>
110
+ </div>
111
+ </div>
112
+
data/scraped/raw/flow_actions.txt ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## How actions work
4
+
5
+ An action is a workflow component in Shopify Flow. It represents a task that's executed in a store or in an app when certain conditions are met. You can connect your app to Shopify Flow so that your app receives data when a workflow action runs.
6
+
7
+ This guide shows you how to add an action to your app so that merchants can use it in their workflows.
8
+
9
+ ![A diagram that show how third party actions interface with Flow ](/assets/apps/flow/action_diagram.png)
10
+
11
+ ## Next steps
12
+
13
+ - Follow our step by step guide on [how to create and test a Flow action](/docs/apps/build/flow/actions/create).
14
+ - Check out our action endpoint guide for more information on how to setup an [execution endpoint](/docs/apps/build/flow/actions/endpoints#flow-action-execution), a [custom configuration page preview endpoint](/docs/apps/build/flow/actions/endpoints#custom-configuration-page-preview) and [custom validation](/docs/apps/build/flow/actions/endpoints#custom-validation).
15
+ - Learn more about how to [return complex data](/docs/apps/build/flow/configure-complex-data-types) in a Flow action.
16
+ - Interested in building a custom configuration page? Follow this [guide](/docs/apps/build/flow/actions/build-config-ui) to learn more.
data/scraped/raw/flow_actions_build-config-ui.txt ADDED
@@ -0,0 +1,895 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ To give merchants a more seamless action configuration experience, and to allow them to manage resources that are external to Shopify Flow, you can embed a page from your app in the Shopify Flow editor.
4
+
5
+ In your Shopify Flow action configuration, merchants see a preview with an image and text that's fetched from your [custom configuration page preview URL](/docs/apps/build/flow/actions/endpoints#custom-configuration-page-preview). Merchants can click the button to access the custom configuration page.
6
+
7
+ <figure class="figure"><img src="https://cdn.shopify.com/shopifycloud/shopify_dev/assets/apps/flow/ccp-preview-d0bce046a2f45d366041698ab3e42abbf3ebd3a191696e16acaecb7718da5afb.png" class="lazyload" alt="A custom configuration page preview with an "Edit Email" button." width="899" height="737"></figure>
8
+
9
+ Your custom configuration page is then displayed in a frame in the Shopify admin.
10
+
11
+ <figure class="figure"><img src="https://cdn.shopify.com/shopifycloud/shopify_dev/assets/apps/flow/ccp-app-bridge-a41ecd52945725531037786df500785ea47a89f16b7df392e19be619bd133f64.png" class="lazyload" alt="The custom configuration page is rendered with an App Bridge title bar." width="1253" height="756"></figure>
12
+
13
+ In this tutorial, you'll learn how to render a custom configuration page in Shopify Flow, customize the page frame, and access data relevant to your action in the custom configuration page context.
14
+
15
+ ## Requirements
16
+
17
+ - You've created a [Partner account](https://www.shopify.com/partners).
18
+ - You've [created an app](/docs/apps/build/scaffold-app).
19
+
20
+ ## Resources
21
+
22
+ To implement this feature, you'll use the following:
23
+
24
+ - [Shopify App Bridge](/docs/api/app-bridge)
25
+ - App Bridge components
26
+ - App Bridge actions specific to the custom configuration page
27
+
28
+ ## Implementing a custom configuration page
29
+
30
+ To build a custom configuration page, you'll [use Shopify App Bridge to render a page from your app page in Shopify Flow](#use-shopify-app-bridge-to-render-your-app-page).
31
+
32
+ From the context of the custom configuration page, you can then [access step and property information](#access-action-information) that you can use to display the appropriate information.
33
+
34
+ You can also [add additional buttons](#add-buttons-to-the-app-bridge-title-bar) to the App Bridge title bar, or [trigger a redirect to the previous page](#return-to-the-previous-page).
35
+
36
+ ## Use Shopify App Bridge to render your app page
37
+
38
+ > Note:
39
+ > The specifics of the Custom Configuration Page integration varies between Shopify App Bridge versions. Make sure you implement the integration specific to your Shopify App Bridge version.
40
+
41
+ To render your custom configuration page, you need to integrate Shopify App Bridge on the route that you want to render. To learn about setting up Shopify App Bridge, refer to one of the following pages:
42
+
43
+ - [Getting started with Shopify App Bridge](/docs/api/app-bridge/previous-versions/app-bridge-from-npm/app-setup)
44
+ - [Getting started with App Bridge React](/docs/api/app-bridge-library#react)
45
+
46
+ ### Access action information
47
+
48
+ In the context of the custom configuration page, Shopify Flow makes the following action information available:
49
+
50
+ - **A `step_reference` search parameter**: `step_reference` is a unique ID for the step within a workflow, and can be used to identify the resource that the merchant is requesting.
51
+ - **Property data**: Properties contains the extension fields data that make up your [action payload schema](/docs/apps/build/flow/actions/endpoints#request). The properties are passed as an object containing the properties as key-value pairs:
52
+
53
+ <p>
54
+ <div class="react-code-block" data-preset="basic">
55
+ <div class="react-code-block-preload ThemeMode-dim">
56
+ <div class="react-code-block-preload-bar basic-codeblock"></div>
57
+ <div class="react-code-block-preload-placeholder-container">
58
+ <div class="react-code-block-preload-code-container">
59
+ <div class="react-code-block-preload-codeline-number"></div>
60
+ <div class="react-code-block-preload-codeline"></div>
61
+ </div>
62
+ <div class="react-code-block-preload-code-container">
63
+ <div class="react-code-block-preload-codeline-number"></div>
64
+ <div class="react-code-block-preload-codeline"></div>
65
+ </div>
66
+ <div class="react-code-block-preload-code-container">
67
+ <div class="react-code-block-preload-codeline-number"></div>
68
+ <div class="react-code-block-preload-codeline"></div>
69
+ </div>
70
+
71
+ </div>
72
+ </div>
73
+
74
+
75
+ <script type="text/plain" data-language="json">
76
+ RAW_MD_CONTENT{
77
+ <property-name>: <property-value>
78
+ }
79
+ END_RAW_MD_CONTENT</script>
80
+
81
+ </div>
82
+ </p>
83
+
84
+
85
+ ### Shopify App Bridge integration for versions 4.X.X and up
86
+
87
+ #### Register to the Custom Configuration Page's intent
88
+
89
+ To access property data with Shopify App Bridge version 4.X.X and up, you will need to use the `shopify.intents` API. The following example code allows you to register to the Custom Configuration Page's intent:
90
+
91
+ <p>
92
+ <div class="react-code-block" data-preset="file">
93
+ <div class="react-code-block-preload ThemeMode-dim">
94
+ <div class="react-code-block-preload-bar "></div>
95
+ <div class="react-code-block-preload-placeholder-container">
96
+ <div class="react-code-block-preload-code-container">
97
+ <div class="react-code-block-preload-codeline-number"></div>
98
+ <div class="react-code-block-preload-codeline"></div>
99
+ </div>
100
+ <div class="react-code-block-preload-code-container">
101
+ <div class="react-code-block-preload-codeline-number"></div>
102
+ <div class="react-code-block-preload-codeline"></div>
103
+ </div>
104
+ <div class="react-code-block-preload-code-container">
105
+ <div class="react-code-block-preload-codeline-number"></div>
106
+ <div class="react-code-block-preload-codeline"></div>
107
+ </div>
108
+ <div class="react-code-block-preload-code-container">
109
+ <div class="react-code-block-preload-codeline-number"></div>
110
+ <div class="react-code-block-preload-codeline"></div>
111
+ </div>
112
+ <div class="react-code-block-preload-code-container">
113
+ <div class="react-code-block-preload-codeline-number"></div>
114
+ <div class="react-code-block-preload-codeline"></div>
115
+ </div>
116
+ <div class="react-code-block-preload-code-container">
117
+ <div class="react-code-block-preload-codeline-number"></div>
118
+ <div class="react-code-block-preload-codeline"></div>
119
+ </div>
120
+ <div class="react-code-block-preload-code-container">
121
+ <div class="react-code-block-preload-codeline-number"></div>
122
+ <div class="react-code-block-preload-codeline"></div>
123
+ </div>
124
+ <div class="react-code-block-preload-code-container">
125
+ <div class="react-code-block-preload-codeline-number"></div>
126
+ <div class="react-code-block-preload-codeline"></div>
127
+ </div>
128
+ <div class="react-code-block-preload-code-container">
129
+ <div class="react-code-block-preload-codeline-number"></div>
130
+ <div class="react-code-block-preload-codeline"></div>
131
+ </div>
132
+ <div class="react-code-block-preload-code-container">
133
+ <div class="react-code-block-preload-codeline-number"></div>
134
+ <div class="react-code-block-preload-codeline"></div>
135
+ </div>
136
+ <div class="react-code-block-preload-code-container">
137
+ <div class="react-code-block-preload-codeline-number"></div>
138
+ <div class="react-code-block-preload-codeline"></div>
139
+ </div>
140
+ <div class="react-code-block-preload-code-container">
141
+ <div class="react-code-block-preload-codeline-number"></div>
142
+ <div class="react-code-block-preload-codeline"></div>
143
+ </div>
144
+ <div class="react-code-block-preload-code-container">
145
+ <div class="react-code-block-preload-codeline-number"></div>
146
+ <div class="react-code-block-preload-codeline"></div>
147
+ </div>
148
+ <div class="react-code-block-preload-code-container">
149
+ <div class="react-code-block-preload-codeline-number"></div>
150
+ <div class="react-code-block-preload-codeline"></div>
151
+ </div>
152
+ <div class="react-code-block-preload-code-container">
153
+ <div class="react-code-block-preload-codeline-number"></div>
154
+ <div class="react-code-block-preload-codeline"></div>
155
+ </div>
156
+ <div class="react-code-block-preload-code-container">
157
+ <div class="react-code-block-preload-codeline-number"></div>
158
+ <div class="react-code-block-preload-codeline"></div>
159
+ </div>
160
+
161
+ </div>
162
+ </div>
163
+
164
+ <script data-option="filename" data-value="Example"></script>
165
+
166
+ <script type="text/plain" data-language="jsx" data-title="React">
167
+ RAW_MD_CONTENTimport { useAppBridge } from '@shopify/app-bridge-react'
168
+
169
+ const Application = () => {
170
+ const shopify = useAppBridge()
171
+ const [intent, setIntent] = useState({})
172
+
173
+ useEffect(() => {
174
+ const cleanup = shopify.intents.register((intent) => {
175
+ setIntent(intent)
176
+ })
177
+
178
+ return () => cleanup()
179
+ }, []);
180
+
181
+ return <>...</>
182
+ }
183
+ END_RAW_MD_CONTENT</script>
184
+
185
+ </div>
186
+ </p>
187
+
188
+
189
+ The `intent` object will contain the following data:
190
+
191
+ | Field | Data Type | Description |
192
+ | ------- | --------- | ----------------------------------------------------------------------------------------------------- |
193
+ | action | `string` | The action that has been registered for. In the case of the Custom Configuration Page, it will always be set to `configure`. |
194
+ | type | `string` | A GID with the following structure: `gid://flow/stepReference/<step-reference>`. |
195
+ | data | `object` | An object that contains the `properties` data. |
196
+ | finish | `method` | A function that allows you to navigate to the previous page. |
197
+
198
+ The register method also returns a cleanup function, which you can use to unregister from the intent when your component is unmounting.
199
+
200
+ #### Return to the previous page
201
+
202
+ By default, the title bar of the custom configuration page includes an **Exit** button that the user can use to return to the previous page. You can choose to trigger a redirect to the previous page using the `intent.finish()` method:
203
+
204
+ <p>
205
+ <div class="react-code-block" data-preset="file">
206
+ <div class="react-code-block-preload ThemeMode-dim">
207
+ <div class="react-code-block-preload-bar "></div>
208
+ <div class="react-code-block-preload-placeholder-container">
209
+ <div class="react-code-block-preload-code-container">
210
+ <div class="react-code-block-preload-codeline-number"></div>
211
+ <div class="react-code-block-preload-codeline"></div>
212
+ </div>
213
+ <div class="react-code-block-preload-code-container">
214
+ <div class="react-code-block-preload-codeline-number"></div>
215
+ <div class="react-code-block-preload-codeline"></div>
216
+ </div>
217
+ <div class="react-code-block-preload-code-container">
218
+ <div class="react-code-block-preload-codeline-number"></div>
219
+ <div class="react-code-block-preload-codeline"></div>
220
+ </div>
221
+ <div class="react-code-block-preload-code-container">
222
+ <div class="react-code-block-preload-codeline-number"></div>
223
+ <div class="react-code-block-preload-codeline"></div>
224
+ </div>
225
+ <div class="react-code-block-preload-code-container">
226
+ <div class="react-code-block-preload-codeline-number"></div>
227
+ <div class="react-code-block-preload-codeline"></div>
228
+ </div>
229
+ <div class="react-code-block-preload-code-container">
230
+ <div class="react-code-block-preload-codeline-number"></div>
231
+ <div class="react-code-block-preload-codeline"></div>
232
+ </div>
233
+ <div class="react-code-block-preload-code-container">
234
+ <div class="react-code-block-preload-codeline-number"></div>
235
+ <div class="react-code-block-preload-codeline"></div>
236
+ </div>
237
+ <div class="react-code-block-preload-code-container">
238
+ <div class="react-code-block-preload-codeline-number"></div>
239
+ <div class="react-code-block-preload-codeline"></div>
240
+ </div>
241
+
242
+ </div>
243
+ </div>
244
+
245
+ <script data-option="filename" data-value="Example"></script>
246
+
247
+ <script type="text/plain" data-language="jsx" data-title="React">
248
+ RAW_MD_CONTENT<Button
249
+ primary
250
+ onClick={() => {
251
+ intent.finish()
252
+ }}
253
+ >
254
+ Go back to Flow
255
+ </Button>
256
+ END_RAW_MD_CONTENT</script>
257
+
258
+ </div>
259
+ </p>
260
+
261
+
262
+ #### Add buttons to the App Bridge title bar
263
+
264
+ You can add more actions to the navigation bar by using the **[ui-title-bar](/docs/api/app-bridge-library/web-components/ui-title-bar)** element. Only primary and secondary actions are supported.
265
+
266
+ <p>
267
+ <div class="react-code-block" data-preset="file">
268
+ <div class="react-code-block-preload ThemeMode-dim">
269
+ <div class="react-code-block-preload-bar "></div>
270
+ <div class="react-code-block-preload-placeholder-container">
271
+ <div class="react-code-block-preload-code-container">
272
+ <div class="react-code-block-preload-codeline-number"></div>
273
+ <div class="react-code-block-preload-codeline"></div>
274
+ </div>
275
+ <div class="react-code-block-preload-code-container">
276
+ <div class="react-code-block-preload-codeline-number"></div>
277
+ <div class="react-code-block-preload-codeline"></div>
278
+ </div>
279
+ <div class="react-code-block-preload-code-container">
280
+ <div class="react-code-block-preload-codeline-number"></div>
281
+ <div class="react-code-block-preload-codeline"></div>
282
+ </div>
283
+ <div class="react-code-block-preload-code-container">
284
+ <div class="react-code-block-preload-codeline-number"></div>
285
+ <div class="react-code-block-preload-codeline"></div>
286
+ </div>
287
+ <div class="react-code-block-preload-code-container">
288
+ <div class="react-code-block-preload-codeline-number"></div>
289
+ <div class="react-code-block-preload-codeline"></div>
290
+ </div>
291
+ <div class="react-code-block-preload-code-container">
292
+ <div class="react-code-block-preload-codeline-number"></div>
293
+ <div class="react-code-block-preload-codeline"></div>
294
+ </div>
295
+ <div class="react-code-block-preload-code-container">
296
+ <div class="react-code-block-preload-codeline-number"></div>
297
+ <div class="react-code-block-preload-codeline"></div>
298
+ </div>
299
+ <div class="react-code-block-preload-code-container">
300
+ <div class="react-code-block-preload-codeline-number"></div>
301
+ <div class="react-code-block-preload-codeline"></div>
302
+ </div>
303
+ <div class="react-code-block-preload-code-container">
304
+ <div class="react-code-block-preload-codeline-number"></div>
305
+ <div class="react-code-block-preload-codeline"></div>
306
+ </div>
307
+ <div class="react-code-block-preload-code-container">
308
+ <div class="react-code-block-preload-codeline-number"></div>
309
+ <div class="react-code-block-preload-codeline"></div>
310
+ </div>
311
+
312
+ </div>
313
+ </div>
314
+
315
+ <script data-option="filename" data-value="Example"></script>
316
+
317
+ <script type="text/plain" data-language="jsx" data-title="React">
318
+ RAW_MD_CONTENTfunction Page() {
319
+ return <ui-title-bar>
320
+ <button variant="primary" onClick={() => console.log('Primary action')}>
321
+ Primary action
322
+ </button>
323
+ <button onClick={() => console.log('Secondary action')}>
324
+ Secondary action
325
+ </button>
326
+ </ui-title-bar>
327
+ }
328
+ END_RAW_MD_CONTENT</script>
329
+
330
+ </div>
331
+ </p>
332
+
333
+
334
+ ### Shopify App Bridge integration for versions 3.X.X and down
335
+
336
+ #### Request property data
337
+
338
+ To access property data, you need to subscribe to `APP::APP_FRAME::PROPERTIES_EVENT`, and then request the properties by triggering the `APP::APP_FRAME::REQUEST_PROPERTIES` event. The following example code subscribes to the properties event and requests the action properties in React:
339
+
340
+ <p>
341
+ <div class="react-code-block" data-preset="file">
342
+ <div class="react-code-block-preload ThemeMode-dim">
343
+ <div class="react-code-block-preload-bar "></div>
344
+ <div class="react-code-block-preload-placeholder-container">
345
+ <div class="react-code-block-preload-code-container">
346
+ <div class="react-code-block-preload-codeline-number"></div>
347
+ <div class="react-code-block-preload-codeline"></div>
348
+ </div>
349
+ <div class="react-code-block-preload-code-container">
350
+ <div class="react-code-block-preload-codeline-number"></div>
351
+ <div class="react-code-block-preload-codeline"></div>
352
+ </div>
353
+ <div class="react-code-block-preload-code-container">
354
+ <div class="react-code-block-preload-codeline-number"></div>
355
+ <div class="react-code-block-preload-codeline"></div>
356
+ </div>
357
+ <div class="react-code-block-preload-code-container">
358
+ <div class="react-code-block-preload-codeline-number"></div>
359
+ <div class="react-code-block-preload-codeline"></div>
360
+ </div>
361
+ <div class="react-code-block-preload-code-container">
362
+ <div class="react-code-block-preload-codeline-number"></div>
363
+ <div class="react-code-block-preload-codeline"></div>
364
+ </div>
365
+ <div class="react-code-block-preload-code-container">
366
+ <div class="react-code-block-preload-codeline-number"></div>
367
+ <div class="react-code-block-preload-codeline"></div>
368
+ </div>
369
+ <div class="react-code-block-preload-code-container">
370
+ <div class="react-code-block-preload-codeline-number"></div>
371
+ <div class="react-code-block-preload-codeline"></div>
372
+ </div>
373
+ <div class="react-code-block-preload-code-container">
374
+ <div class="react-code-block-preload-codeline-number"></div>
375
+ <div class="react-code-block-preload-codeline"></div>
376
+ </div>
377
+ <div class="react-code-block-preload-code-container">
378
+ <div class="react-code-block-preload-codeline-number"></div>
379
+ <div class="react-code-block-preload-codeline"></div>
380
+ </div>
381
+ <div class="react-code-block-preload-code-container">
382
+ <div class="react-code-block-preload-codeline-number"></div>
383
+ <div class="react-code-block-preload-codeline"></div>
384
+ </div>
385
+ <div class="react-code-block-preload-code-container">
386
+ <div class="react-code-block-preload-codeline-number"></div>
387
+ <div class="react-code-block-preload-codeline"></div>
388
+ </div>
389
+ <div class="react-code-block-preload-code-container">
390
+ <div class="react-code-block-preload-codeline-number"></div>
391
+ <div class="react-code-block-preload-codeline"></div>
392
+ </div>
393
+ <div class="react-code-block-preload-code-container">
394
+ <div class="react-code-block-preload-codeline-number"></div>
395
+ <div class="react-code-block-preload-codeline"></div>
396
+ </div>
397
+ <div class="react-code-block-preload-code-container">
398
+ <div class="react-code-block-preload-codeline-number"></div>
399
+ <div class="react-code-block-preload-codeline"></div>
400
+ </div>
401
+ <div class="react-code-block-preload-code-container">
402
+ <div class="react-code-block-preload-codeline-number"></div>
403
+ <div class="react-code-block-preload-codeline"></div>
404
+ </div>
405
+ <div class="react-code-block-preload-code-container">
406
+ <div class="react-code-block-preload-codeline-number"></div>
407
+ <div class="react-code-block-preload-codeline"></div>
408
+ </div>
409
+ <div class="react-code-block-preload-code-container">
410
+ <div class="react-code-block-preload-codeline-number"></div>
411
+ <div class="react-code-block-preload-codeline"></div>
412
+ </div>
413
+ <div class="react-code-block-preload-code-container">
414
+ <div class="react-code-block-preload-codeline-number"></div>
415
+ <div class="react-code-block-preload-codeline"></div>
416
+ </div>
417
+ <div class="react-code-block-preload-code-container">
418
+ <div class="react-code-block-preload-codeline-number"></div>
419
+ <div class="react-code-block-preload-codeline"></div>
420
+ </div>
421
+ <div class="react-code-block-preload-code-container">
422
+ <div class="react-code-block-preload-codeline-number"></div>
423
+ <div class="react-code-block-preload-codeline"></div>
424
+ </div>
425
+ <div class="react-code-block-preload-code-container">
426
+ <div class="react-code-block-preload-codeline-number"></div>
427
+ <div class="react-code-block-preload-codeline"></div>
428
+ </div>
429
+ <div class="react-code-block-preload-code-container">
430
+ <div class="react-code-block-preload-codeline-number"></div>
431
+ <div class="react-code-block-preload-codeline"></div>
432
+ </div>
433
+ <div class="react-code-block-preload-code-container">
434
+ <div class="react-code-block-preload-codeline-number"></div>
435
+ <div class="react-code-block-preload-codeline"></div>
436
+ </div>
437
+ <div class="react-code-block-preload-code-container">
438
+ <div class="react-code-block-preload-codeline-number"></div>
439
+ <div class="react-code-block-preload-codeline"></div>
440
+ </div>
441
+ <div class="react-code-block-preload-code-container">
442
+ <div class="react-code-block-preload-codeline-number"></div>
443
+ <div class="react-code-block-preload-codeline"></div>
444
+ </div>
445
+ <div class="react-code-block-preload-code-container">
446
+ <div class="react-code-block-preload-codeline-number"></div>
447
+ <div class="react-code-block-preload-codeline"></div>
448
+ </div>
449
+
450
+ </div>
451
+ </div>
452
+
453
+ <script data-option="filename" data-value="Example"></script>
454
+
455
+ <script type="text/plain" data-language="jsx">
456
+ RAW_MD_CONTENTimport { useAppBridge } from '@shopify/app-bridge-react'
457
+
458
+ const Application = () => {
459
+ const app = useAppBridge()
460
+ const [propertiesData, setPropertiesData] = useState({})
461
+
462
+ useEffect(() => {
463
+ const unsubscribeToPropertiesEvent = app.subscribe(
464
+ 'APP::APP_FRAME::PROPERTIES_EVENT',
465
+ payload => {
466
+ setPropertiesData(payload['properties'])
467
+ },
468
+ )
469
+
470
+ return unsubscribeToPropertiesEvent
471
+ }, [app])
472
+
473
+ useEffect(() => {
474
+ app.dispatch({
475
+ type: 'APP::APP_FRAME::REQUEST_PROPERTIES',
476
+ group: 'AppFrame',
477
+ })
478
+ }, [])
479
+
480
+ return (...)
481
+ }
482
+ END_RAW_MD_CONTENT</script>
483
+
484
+ </div>
485
+ </p>
486
+
487
+
488
+ #### Return to the previous page
489
+
490
+ By default, the title bar of the custom configuration page includes an **Exit** button that the user can use to return to the previous page. This might be the Shopify Flow editor. However, you can choose to trigger a redirect to the previous page using `APP::APP_FRAME::NAVIGATE_BACK`:
491
+
492
+ <p>
493
+ <div class="react-code-block" data-preset="file">
494
+ <div class="react-code-block-preload ThemeMode-dim">
495
+ <div class="react-code-block-preload-bar "></div>
496
+ <div class="react-code-block-preload-placeholder-container">
497
+ <div class="react-code-block-preload-code-container">
498
+ <div class="react-code-block-preload-codeline-number"></div>
499
+ <div class="react-code-block-preload-codeline"></div>
500
+ </div>
501
+ <div class="react-code-block-preload-code-container">
502
+ <div class="react-code-block-preload-codeline-number"></div>
503
+ <div class="react-code-block-preload-codeline"></div>
504
+ </div>
505
+ <div class="react-code-block-preload-code-container">
506
+ <div class="react-code-block-preload-codeline-number"></div>
507
+ <div class="react-code-block-preload-codeline"></div>
508
+ </div>
509
+ <div class="react-code-block-preload-code-container">
510
+ <div class="react-code-block-preload-codeline-number"></div>
511
+ <div class="react-code-block-preload-codeline"></div>
512
+ </div>
513
+
514
+ </div>
515
+ </div>
516
+
517
+ <script data-option="filename" data-value="Example"></script>
518
+
519
+ <script type="text/plain" data-language="jsx">
520
+ RAW_MD_CONTENTapp.dispatch({
521
+ type: 'APP::APP_FRAME::NAVIGATE_BACK',
522
+ group: 'AppFrame',
523
+ })
524
+
525
+ END_RAW_MD_CONTENT</script>
526
+
527
+ </div>
528
+ </p>
529
+
530
+
531
+ #### Add buttons to the App Bridge title bar
532
+
533
+ You can add more actions to the App Bridge title bar in one of two ways:
534
+
535
+ - Using `@shopify/app-bridge`: Use the [`Button.create`](/docs/api/app-bridge/previous-versions/actions/button#create-a-button) initializer to create the buttons, then pass them to the [`Titlebar.create`](/docs/api/app-bridge/previous-versions/actions/titlebar#plain-javascript) initializer to set the buttons. You need to keep a reference to the Titlebar instance if you wish to do additional updates after the initialization.
536
+ - Using `@shopify/app-bridge-react`: Pass the primary and secondary actions to the [`TitleBar`](/docs/api/app-bridge/previous-versions/actions/titlebar#react) React component.
537
+
538
+ Only primary and secondary actions on the TitleBar are supported. Other App Bridge actions are ignored.
539
+
540
+ <p>
541
+ <div class="react-code-block" data-preset="file">
542
+ <div class="react-code-block-preload ThemeMode-dim">
543
+ <div class="react-code-block-preload-bar "></div>
544
+ <div class="react-code-block-preload-placeholder-container">
545
+ <div class="react-code-block-preload-code-container">
546
+ <div class="react-code-block-preload-codeline-number"></div>
547
+ <div class="react-code-block-preload-codeline"></div>
548
+ </div>
549
+ <div class="react-code-block-preload-code-container">
550
+ <div class="react-code-block-preload-codeline-number"></div>
551
+ <div class="react-code-block-preload-codeline"></div>
552
+ </div>
553
+ <div class="react-code-block-preload-code-container">
554
+ <div class="react-code-block-preload-codeline-number"></div>
555
+ <div class="react-code-block-preload-codeline"></div>
556
+ </div>
557
+ <div class="react-code-block-preload-code-container">
558
+ <div class="react-code-block-preload-codeline-number"></div>
559
+ <div class="react-code-block-preload-codeline"></div>
560
+ </div>
561
+ <div class="react-code-block-preload-code-container">
562
+ <div class="react-code-block-preload-codeline-number"></div>
563
+ <div class="react-code-block-preload-codeline"></div>
564
+ </div>
565
+ <div class="react-code-block-preload-code-container">
566
+ <div class="react-code-block-preload-codeline-number"></div>
567
+ <div class="react-code-block-preload-codeline"></div>
568
+ </div>
569
+ <div class="react-code-block-preload-code-container">
570
+ <div class="react-code-block-preload-codeline-number"></div>
571
+ <div class="react-code-block-preload-codeline"></div>
572
+ </div>
573
+ <div class="react-code-block-preload-code-container">
574
+ <div class="react-code-block-preload-codeline-number"></div>
575
+ <div class="react-code-block-preload-codeline"></div>
576
+ </div>
577
+ <div class="react-code-block-preload-code-container">
578
+ <div class="react-code-block-preload-codeline-number"></div>
579
+ <div class="react-code-block-preload-codeline"></div>
580
+ </div>
581
+ <div class="react-code-block-preload-code-container">
582
+ <div class="react-code-block-preload-codeline-number"></div>
583
+ <div class="react-code-block-preload-codeline"></div>
584
+ </div>
585
+ <div class="react-code-block-preload-code-container">
586
+ <div class="react-code-block-preload-codeline-number"></div>
587
+ <div class="react-code-block-preload-codeline"></div>
588
+ </div>
589
+ <div class="react-code-block-preload-code-container">
590
+ <div class="react-code-block-preload-codeline-number"></div>
591
+ <div class="react-code-block-preload-codeline"></div>
592
+ </div>
593
+ <div class="react-code-block-preload-code-container">
594
+ <div class="react-code-block-preload-codeline-number"></div>
595
+ <div class="react-code-block-preload-codeline"></div>
596
+ </div>
597
+ <div class="react-code-block-preload-code-container">
598
+ <div class="react-code-block-preload-codeline-number"></div>
599
+ <div class="react-code-block-preload-codeline"></div>
600
+ </div>
601
+ <div class="react-code-block-preload-code-container">
602
+ <div class="react-code-block-preload-codeline-number"></div>
603
+ <div class="react-code-block-preload-codeline"></div>
604
+ </div>
605
+ <div class="react-code-block-preload-code-container">
606
+ <div class="react-code-block-preload-codeline-number"></div>
607
+ <div class="react-code-block-preload-codeline"></div>
608
+ </div>
609
+ <div class="react-code-block-preload-code-container">
610
+ <div class="react-code-block-preload-codeline-number"></div>
611
+ <div class="react-code-block-preload-codeline"></div>
612
+ </div>
613
+ <div class="react-code-block-preload-code-container">
614
+ <div class="react-code-block-preload-codeline-number"></div>
615
+ <div class="react-code-block-preload-codeline"></div>
616
+ </div>
617
+ <div class="react-code-block-preload-code-container">
618
+ <div class="react-code-block-preload-codeline-number"></div>
619
+ <div class="react-code-block-preload-codeline"></div>
620
+ </div>
621
+ <div class="react-code-block-preload-code-container">
622
+ <div class="react-code-block-preload-codeline-number"></div>
623
+ <div class="react-code-block-preload-codeline"></div>
624
+ </div>
625
+ <div class="react-code-block-preload-code-container">
626
+ <div class="react-code-block-preload-codeline-number"></div>
627
+ <div class="react-code-block-preload-codeline"></div>
628
+ </div>
629
+ <div class="react-code-block-preload-code-container">
630
+ <div class="react-code-block-preload-codeline-number"></div>
631
+ <div class="react-code-block-preload-codeline"></div>
632
+ </div>
633
+ <div class="react-code-block-preload-code-container">
634
+ <div class="react-code-block-preload-codeline-number"></div>
635
+ <div class="react-code-block-preload-codeline"></div>
636
+ </div>
637
+ <div class="react-code-block-preload-code-container">
638
+ <div class="react-code-block-preload-codeline-number"></div>
639
+ <div class="react-code-block-preload-codeline"></div>
640
+ </div>
641
+ <div class="react-code-block-preload-code-container">
642
+ <div class="react-code-block-preload-codeline-number"></div>
643
+ <div class="react-code-block-preload-codeline"></div>
644
+ </div>
645
+ <div class="react-code-block-preload-code-container">
646
+ <div class="react-code-block-preload-codeline-number"></div>
647
+ <div class="react-code-block-preload-codeline"></div>
648
+ </div>
649
+ <div class="react-code-block-preload-code-container">
650
+ <div class="react-code-block-preload-codeline-number"></div>
651
+ <div class="react-code-block-preload-codeline"></div>
652
+ </div>
653
+ <div class="react-code-block-preload-code-container">
654
+ <div class="react-code-block-preload-codeline-number"></div>
655
+ <div class="react-code-block-preload-codeline"></div>
656
+ </div>
657
+ <div class="react-code-block-preload-code-container">
658
+ <div class="react-code-block-preload-codeline-number"></div>
659
+ <div class="react-code-block-preload-codeline"></div>
660
+ </div>
661
+ <div class="react-code-block-preload-code-container">
662
+ <div class="react-code-block-preload-codeline-number"></div>
663
+ <div class="react-code-block-preload-codeline"></div>
664
+ </div>
665
+ <div class="react-code-block-preload-code-container">
666
+ <div class="react-code-block-preload-codeline-number"></div>
667
+ <div class="react-code-block-preload-codeline"></div>
668
+ </div>
669
+ <div class="react-code-block-preload-code-container">
670
+ <div class="react-code-block-preload-codeline-number"></div>
671
+ <div class="react-code-block-preload-codeline"></div>
672
+ </div>
673
+ <div class="react-code-block-preload-code-container">
674
+ <div class="react-code-block-preload-codeline-number"></div>
675
+ <div class="react-code-block-preload-codeline"></div>
676
+ </div>
677
+ <div class="react-code-block-preload-code-container">
678
+ <div class="react-code-block-preload-codeline-number"></div>
679
+ <div class="react-code-block-preload-codeline"></div>
680
+ </div>
681
+ <div class="react-code-block-preload-code-container">
682
+ <div class="react-code-block-preload-codeline-number"></div>
683
+ <div class="react-code-block-preload-codeline"></div>
684
+ </div>
685
+ <div class="react-code-block-preload-code-container">
686
+ <div class="react-code-block-preload-codeline-number"></div>
687
+ <div class="react-code-block-preload-codeline"></div>
688
+ </div>
689
+ <div class="react-code-block-preload-code-container">
690
+ <div class="react-code-block-preload-codeline-number"></div>
691
+ <div class="react-code-block-preload-codeline"></div>
692
+ </div>
693
+ <div class="react-code-block-preload-code-container">
694
+ <div class="react-code-block-preload-codeline-number"></div>
695
+ <div class="react-code-block-preload-codeline"></div>
696
+ </div>
697
+ <div class="react-code-block-preload-code-container">
698
+ <div class="react-code-block-preload-codeline-number"></div>
699
+ <div class="react-code-block-preload-codeline"></div>
700
+ </div>
701
+ <div class="react-code-block-preload-code-container">
702
+ <div class="react-code-block-preload-codeline-number"></div>
703
+ <div class="react-code-block-preload-codeline"></div>
704
+ </div>
705
+ <div class="react-code-block-preload-code-container">
706
+ <div class="react-code-block-preload-codeline-number"></div>
707
+ <div class="react-code-block-preload-codeline"></div>
708
+ </div>
709
+ <div class="react-code-block-preload-code-container">
710
+ <div class="react-code-block-preload-codeline-number"></div>
711
+ <div class="react-code-block-preload-codeline"></div>
712
+ </div>
713
+ <div class="react-code-block-preload-code-container">
714
+ <div class="react-code-block-preload-codeline-number"></div>
715
+ <div class="react-code-block-preload-codeline"></div>
716
+ </div>
717
+ <div class="react-code-block-preload-code-container">
718
+ <div class="react-code-block-preload-codeline-number"></div>
719
+ <div class="react-code-block-preload-codeline"></div>
720
+ </div>
721
+ <div class="react-code-block-preload-code-container">
722
+ <div class="react-code-block-preload-codeline-number"></div>
723
+ <div class="react-code-block-preload-codeline"></div>
724
+ </div>
725
+ <div class="react-code-block-preload-code-container">
726
+ <div class="react-code-block-preload-codeline-number"></div>
727
+ <div class="react-code-block-preload-codeline"></div>
728
+ </div>
729
+ <div class="react-code-block-preload-code-container">
730
+ <div class="react-code-block-preload-codeline-number"></div>
731
+ <div class="react-code-block-preload-codeline"></div>
732
+ </div>
733
+ <div class="react-code-block-preload-code-container">
734
+ <div class="react-code-block-preload-codeline-number"></div>
735
+ <div class="react-code-block-preload-codeline"></div>
736
+ </div>
737
+ <div class="react-code-block-preload-code-container">
738
+ <div class="react-code-block-preload-codeline-number"></div>
739
+ <div class="react-code-block-preload-codeline"></div>
740
+ </div>
741
+ <div class="react-code-block-preload-code-container">
742
+ <div class="react-code-block-preload-codeline-number"></div>
743
+ <div class="react-code-block-preload-codeline"></div>
744
+ </div>
745
+ <div class="react-code-block-preload-code-container">
746
+ <div class="react-code-block-preload-codeline-number"></div>
747
+ <div class="react-code-block-preload-codeline"></div>
748
+ </div>
749
+ <div class="react-code-block-preload-code-container">
750
+ <div class="react-code-block-preload-codeline-number"></div>
751
+ <div class="react-code-block-preload-codeline"></div>
752
+ </div>
753
+ <div class="react-code-block-preload-code-container">
754
+ <div class="react-code-block-preload-codeline-number"></div>
755
+ <div class="react-code-block-preload-codeline"></div>
756
+ </div>
757
+ <div class="react-code-block-preload-code-container">
758
+ <div class="react-code-block-preload-codeline-number"></div>
759
+ <div class="react-code-block-preload-codeline"></div>
760
+ </div>
761
+ <div class="react-code-block-preload-code-container">
762
+ <div class="react-code-block-preload-codeline-number"></div>
763
+ <div class="react-code-block-preload-codeline"></div>
764
+ </div>
765
+ <div class="react-code-block-preload-code-container">
766
+ <div class="react-code-block-preload-codeline-number"></div>
767
+ <div class="react-code-block-preload-codeline"></div>
768
+ </div>
769
+ <div class="react-code-block-preload-code-container">
770
+ <div class="react-code-block-preload-codeline-number"></div>
771
+ <div class="react-code-block-preload-codeline"></div>
772
+ </div>
773
+ <div class="react-code-block-preload-code-container">
774
+ <div class="react-code-block-preload-codeline-number"></div>
775
+ <div class="react-code-block-preload-codeline"></div>
776
+ </div>
777
+ <div class="react-code-block-preload-code-container">
778
+ <div class="react-code-block-preload-codeline-number"></div>
779
+ <div class="react-code-block-preload-codeline"></div>
780
+ </div>
781
+ <div class="react-code-block-preload-code-container">
782
+ <div class="react-code-block-preload-codeline-number"></div>
783
+ <div class="react-code-block-preload-codeline"></div>
784
+ </div>
785
+ <div class="react-code-block-preload-code-container">
786
+ <div class="react-code-block-preload-codeline-number"></div>
787
+ <div class="react-code-block-preload-codeline"></div>
788
+ </div>
789
+ <div class="react-code-block-preload-code-container">
790
+ <div class="react-code-block-preload-codeline-number"></div>
791
+ <div class="react-code-block-preload-codeline"></div>
792
+ </div>
793
+ <div class="react-code-block-preload-code-container">
794
+ <div class="react-code-block-preload-codeline-number"></div>
795
+ <div class="react-code-block-preload-codeline"></div>
796
+ </div>
797
+ <div class="react-code-block-preload-code-container">
798
+ <div class="react-code-block-preload-codeline-number"></div>
799
+ <div class="react-code-block-preload-codeline"></div>
800
+ </div>
801
+ <div class="react-code-block-preload-code-container">
802
+ <div class="react-code-block-preload-codeline-number"></div>
803
+ <div class="react-code-block-preload-codeline"></div>
804
+ </div>
805
+
806
+ </div>
807
+ </div>
808
+
809
+ <script data-option="filename" data-value="Example"></script>
810
+
811
+ <script type="text/plain" data-language="js" data-title="JavaScript">
812
+ RAW_MD_CONTENTimport { TitleBar, Button } from '@shopify/app-bridge/actions'
813
+
814
+ // create the buttons
815
+ const primaryBtn = Button.create(app, {
816
+ label: 'Button 1',
817
+ })
818
+ const secondaryBtn = Button.create(app, {
819
+ label: 'Button 2',
820
+ })
821
+
822
+ // add click handlers
823
+ primaryBtn.subscribe(Button.Action.CLICK, () => {
824
+ console.log('button 1 clicked')
825
+ })
826
+ secondaryBtn.subscribe(Button.Action.CLICK, () => {
827
+ console.log('button 2 clicked')
828
+ })
829
+
830
+ const titleBar = TitleBar.create(app, {
831
+ title: '',
832
+ buttons: {
833
+ primary: primaryBtn,
834
+ secondary: [secondaryBtn],
835
+ },
836
+ })
837
+
838
+ // update buttons after initialization
839
+ const newPrimary = Button.create(app, {
840
+ label: 'New button',
841
+ })
842
+ newPrimary.subscribe(Button.Action.CLICK, () => {
843
+ console.log('new primary button clicked')
844
+ })
845
+
846
+ titleBar.set({
847
+ buttons: {
848
+ primary: newPrimary,
849
+ secondary: [secondaryBtn],
850
+ },
851
+ })
852
+
853
+ END_RAW_MD_CONTENT</script>
854
+ <script type="text/plain" data-language="jsx" data-title="React">
855
+ RAW_MD_CONTENTimport { TitleBar } from '@shopify/app-bridge-react'
856
+
857
+ function Page() {
858
+ const buttons = {
859
+ primaryAction: {
860
+ content: 'Button 1',
861
+ onAction: () => {
862
+ console.log('button 1 clicked')
863
+ },
864
+ },
865
+ secondaryActions: [
866
+ {
867
+ content: 'Button 2',
868
+ onAction: () => {
869
+ console.log('button 2 clicked')
870
+ },
871
+ },
872
+ ],
873
+ }
874
+
875
+ return <TitleBar title="" {...buttons} />
876
+ }
877
+ END_RAW_MD_CONTENT</script>
878
+
879
+ </div>
880
+ </p>
881
+
882
+
883
+ ## Next steps
884
+
885
+
886
+
887
+ - Add [custom configuration page preview URL](/docs/apps/build/flow/actions/endpoints#custom-configuration-page-preview) and [custom validation](/docs/apps/build/flow/actions/endpoints#custom-validation) endpoints to your app.
888
+
889
+
890
+
891
+ - Add your custom configuration page preview URL, custom configuration page URL, and custom validation URL to [your Shopify Flow action configuration](/docs/apps/build/flow/actions).
892
+
893
+ > Note:
894
+ > To add a custom configuration page to your action, you also need to add a custom validation endpoint.
895
+
data/scraped/raw/flow_actions_create.txt ADDED
@@ -0,0 +1,298 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ To create an action that merchants can use in their workflows, you need to add the action to your app. The action needs to contain the following information:
4
+
5
+ - The fields that the merchant needs to complete when they add the action to their workflows
6
+ - The URL that Shopify Flow uses to send (POST) the contents (JSON payload) of the action to your app
7
+
8
+ You also need to configure your app to process the data from the POST request when it arrives and to send status codes back to Shopify Flow.
9
+
10
+ To enhance the merchant experience and more closely integrate external systems, you can also [build a custom configuration page](/docs/apps/build/flow/actions/build-config-ui). To improve the reliability of your action, you can add [custom validation](/docs/apps/build/flow/actions/endpoints#custom-validation) for action properties.
11
+
12
+ ## Requirements
13
+
14
+ - You have the following:
15
+ - A test web server that has access to the Internet, so that it can receive POST requests from Shopify Flow
16
+ - A test app that works with the test web server
17
+ - A development store that has [Shopify Flow](https://apps.shopify.com/flow) and the test app installed
18
+
19
+ ## Step 1: Create a Flow Action
20
+
21
+ To give your Flow action a meaningful name, use the following guidelines:
22
+
23
+ - Use a present-tense verb + object acted on format. For example, `Place auction bid`.
24
+ - Use sentence case.
25
+ - Don't use punctuation.
26
+ - Separate words using spaces.
27
+
28
+ ### Using Shopify CLI
29
+
30
+ Use the Shopify CLI to generate a new extension:
31
+
32
+ 1. Navigate to your app directory.
33
+ 2. Run the following command:
34
+
35
+ <p>
36
+ <div class="react-code-block" data-preset="terminal">
37
+ <div class="react-code-block-preload ThemeMode-dim">
38
+ <div class="react-code-block-preload-bar "></div>
39
+ <div class="react-code-block-preload-placeholder-container">
40
+ <div class="react-code-block-preload-code-container">
41
+ <div class="react-code-block-preload-codeline-number"></div>
42
+ <div class="react-code-block-preload-codeline"></div>
43
+ </div>
44
+ <div class="react-code-block-preload-code-container">
45
+ <div class="react-code-block-preload-codeline-number"></div>
46
+ <div class="react-code-block-preload-codeline"></div>
47
+ </div>
48
+
49
+ </div>
50
+ </div>
51
+
52
+
53
+ <script type="text/plain" data-language="bash">
54
+ RAW_MD_CONTENT#!/bin/bash
55
+ shopify app generate extension
56
+ END_RAW_MD_CONTENT</script>
57
+
58
+ </div>
59
+ </p>
60
+
61
+
62
+ 3. Select the `Flow Action` as the type of extension.
63
+ 4. Provide a meaningful name for your extension.
64
+ <br>
65
+
66
+
67
+ After you've followed the prompts, Shopify CLI generates the extension’s file representation in your app's `/extensions` directory and gives you a success message. You can then go into your app's `/extensions` directory and start editing your new extension.
68
+
69
+ The file structure of your extension should look like the following:
70
+
71
+ ```
72
+ /place-auction-bid
73
+ shopify.extension.toml
74
+ ```
75
+
76
+ To learn more about the extensions file structure, refer to [App structure](/docs/apps/build/cli-for-apps/app-structure) and the documentation for your extension type.
77
+
78
+ ### Using the Partner Dashboard
79
+
80
+ 1. In your Partner Dashboard, click [Apps](https://partners.shopify.com/current/apps).
81
+ 2. Select the app that you want to add your Shopify Flow action to.
82
+ 3. Click **Extensions**, then click **Create** or **Create extension**.
83
+ 4. Under the **Flow** tab, click **Flow/Actions**.
84
+ 5. In the **Extension name** field, name your action, such as `Place auction bid`. This name is used only for internal purposes.
85
+ 6. Enter a title and description for the action. In the **Action Preview** area, you can see how the title and action display to merchants when they're choosing actions in Shopify Flow.
86
+ 7. Enter the URL for the action execution endpoint that you created. Shopify Flow sends the action's JSON payload to this endpoint when it's about to execute your action.
87
+
88
+ ## Step 2: Customize a Flow action configuration file
89
+
90
+ In this section you'll use the default action template and update it to be a functional extension example. Once you have generated a Flow extension using Shopify CLI, follow the instructions below:
91
+
92
+ 1. Change the description to `Place a bid on an auction`.
93
+ 2. Update the `extensions.runtime_url` to an endpoint where you can receive the runtime request.
94
+ 3. On the second `settings.fields` field, update the following values:
95
+ - `type` to `number_decimal`
96
+ - `key` to `amount`
97
+ - `name` to `Bid Amount`
98
+ - Add a `description` property and set it to `The amount of the bid`
99
+
100
+ <p>
101
+ <div class="react-code-block" data-preset="file">
102
+ <div class="react-code-block-preload ThemeMode-dim">
103
+ <div class="react-code-block-preload-bar "></div>
104
+ <div class="react-code-block-preload-placeholder-container">
105
+ <div class="react-code-block-preload-code-container">
106
+ <div class="react-code-block-preload-codeline-number"></div>
107
+ <div class="react-code-block-preload-codeline"></div>
108
+ </div>
109
+ <div class="react-code-block-preload-code-container">
110
+ <div class="react-code-block-preload-codeline-number"></div>
111
+ <div class="react-code-block-preload-codeline"></div>
112
+ </div>
113
+ <div class="react-code-block-preload-code-container">
114
+ <div class="react-code-block-preload-codeline-number"></div>
115
+ <div class="react-code-block-preload-codeline"></div>
116
+ </div>
117
+ <div class="react-code-block-preload-code-container">
118
+ <div class="react-code-block-preload-codeline-number"></div>
119
+ <div class="react-code-block-preload-codeline"></div>
120
+ </div>
121
+ <div class="react-code-block-preload-code-container">
122
+ <div class="react-code-block-preload-codeline-number"></div>
123
+ <div class="react-code-block-preload-codeline"></div>
124
+ </div>
125
+ <div class="react-code-block-preload-code-container">
126
+ <div class="react-code-block-preload-codeline-number"></div>
127
+ <div class="react-code-block-preload-codeline"></div>
128
+ </div>
129
+ <div class="react-code-block-preload-code-container">
130
+ <div class="react-code-block-preload-codeline-number"></div>
131
+ <div class="react-code-block-preload-codeline"></div>
132
+ </div>
133
+ <div class="react-code-block-preload-code-container">
134
+ <div class="react-code-block-preload-codeline-number"></div>
135
+ <div class="react-code-block-preload-codeline"></div>
136
+ </div>
137
+ <div class="react-code-block-preload-code-container">
138
+ <div class="react-code-block-preload-codeline-number"></div>
139
+ <div class="react-code-block-preload-codeline"></div>
140
+ </div>
141
+ <div class="react-code-block-preload-code-container">
142
+ <div class="react-code-block-preload-codeline-number"></div>
143
+ <div class="react-code-block-preload-codeline"></div>
144
+ </div>
145
+ <div class="react-code-block-preload-code-container">
146
+ <div class="react-code-block-preload-codeline-number"></div>
147
+ <div class="react-code-block-preload-codeline"></div>
148
+ </div>
149
+ <div class="react-code-block-preload-code-container">
150
+ <div class="react-code-block-preload-codeline-number"></div>
151
+ <div class="react-code-block-preload-codeline"></div>
152
+ </div>
153
+ <div class="react-code-block-preload-code-container">
154
+ <div class="react-code-block-preload-codeline-number"></div>
155
+ <div class="react-code-block-preload-codeline"></div>
156
+ </div>
157
+ <div class="react-code-block-preload-code-container">
158
+ <div class="react-code-block-preload-codeline-number"></div>
159
+ <div class="react-code-block-preload-codeline"></div>
160
+ </div>
161
+ <div class="react-code-block-preload-code-container">
162
+ <div class="react-code-block-preload-codeline-number"></div>
163
+ <div class="react-code-block-preload-codeline"></div>
164
+ </div>
165
+ <div class="react-code-block-preload-code-container">
166
+ <div class="react-code-block-preload-codeline-number"></div>
167
+ <div class="react-code-block-preload-codeline"></div>
168
+ </div>
169
+ <div class="react-code-block-preload-code-container">
170
+ <div class="react-code-block-preload-codeline-number"></div>
171
+ <div class="react-code-block-preload-codeline"></div>
172
+ </div>
173
+ <div class="react-code-block-preload-code-container">
174
+ <div class="react-code-block-preload-codeline-number"></div>
175
+ <div class="react-code-block-preload-codeline"></div>
176
+ </div>
177
+ <div class="react-code-block-preload-code-container">
178
+ <div class="react-code-block-preload-codeline-number"></div>
179
+ <div class="react-code-block-preload-codeline"></div>
180
+ </div>
181
+
182
+ </div>
183
+ </div>
184
+
185
+
186
+ <script type="text/plain" data-language="bash" data-title="toml">
187
+ RAW_MD_CONTENT[[extensions]]
188
+ name = "Place Auction Bid"
189
+ type = "flow_action"
190
+ handle = "place-bid"
191
+ description = "Place a bid on an auction"
192
+ runtime_url = "https://your-server-domain/path/to/action/handler"
193
+
194
+ [settings]
195
+
196
+ [[settings.fields]]
197
+ type = "customer_reference"
198
+ required = true
199
+
200
+ [[settings.fields]]
201
+ type = "number_decimal"
202
+ key = "amount"
203
+ name = "Bid Amount"
204
+ description = "The amount of the bid"
205
+ required = true
206
+ END_RAW_MD_CONTENT</script>
207
+
208
+ </div>
209
+ </p>
210
+
211
+
212
+ ## Step 3: Configure your web server
213
+
214
+ To build a Shopify Flow action, you need to add a service to your web server to listen for the JSON payload that Shopify Flow sends when the action runs.
215
+
216
+ Optionally, you can also add the following:
217
+
218
+ - An endpoint to validate actions
219
+ - A [custom configuration page](/docs/apps/build/flow/actions/build-config-ui), and an endpoint that lets merchants preview your custom configuration page
220
+
221
+ Add the following API endpoints to your server:
222
+
223
+ | Endpoint | Purpose |
224
+ | --- | --- |
225
+ | [Flow action execution](/docs/apps/flow/actions/endpoints#flow-action-execution) | The endpoint where the automation tool sends your action's payload. The payload contains data that you can use to execute the action in your app.|
226
+ | [Custom configuration page preview](/docs/apps/flow/actions/endpoints#custom-configuration-page-preview) | An endpoint that provides data about your [custom configuration page](/docs/apps/build/flow/actions/build-config-ui) to display in the automation tool. This endpoint is required if you want to use a custom configuration page.|
227
+ | [Custom validation](/docs/apps/flow/actions/endpoints#custom-validation) | An endpoint that validates the contents of merchant-configurable properties in an action payload when an action is saved. This endpoint is required if you want to use a custom configuration page.|
228
+
229
+
230
+
231
+ To learn more about the endpoint requirements for your server, refer to [Action endpoints](/docs/apps/build/flow/actions/endpoints).
232
+
233
+ To learn how to create a custom configuration page, refer to [Build a custom configuration page](/docs/apps/build/flow/actions/build-config-ui).
234
+
235
+ ## Step 4: Enable the draft version of your action
236
+
237
+ Running [`app dev`](/docs/api/shopify-cli/app/app-dev) allows changes made to local files to update the draft version of your Flow task extensions. The draft version is only available in your development store.
238
+
239
+ > Note:
240
+ > When [`app dev`](/docs/api/shopify-cli/app/app-dev) is running and "Development store preview" is enabled, the draft version of a task will appear in your development store _in place_ of the deployed version. Other shops will continue to see the deployed version of your task (if one exists). Draft versions can be identified by the "draft" badge. To see the deployed version of the task in your development store, turn off "Development store preview" in the "Extensions" section of your app in [Shopify Partners](https://partners.shopify.com/).
241
+
242
+ 1. Navigate to your app directory.
243
+ 2. Run the following command to start using draft versions of your extension(s):
244
+
245
+ ```bash
246
+ #!/bin/bash
247
+ shopify app dev
248
+ ```
249
+
250
+ 3. Follow the prompts.
251
+
252
+
253
+ ## Step 5: Test the action
254
+
255
+ After you've created an action in the Partner Dashboard and added support for it in your web server, you can test the action in Shopify Flow on your development store.
256
+
257
+ 1. In your development store, create a [workflow](https://www.shopify.com/admin/apps/flow) that uses the action. For example, add the trigger that you created in the [Triggers guide](/docs/apps/build/flow/triggers/create) and this action to a workflow.
258
+
259
+ 2. If you created a custom configuration page, then ensure that the preview displays and that the custom configuration page is accessible.
260
+
261
+ 3. If you added any custom validation, then ensure that it works as expected.
262
+
263
+ 4. Trigger the workflow. For example, in your web server, run the event that sends the trigger information to Shopify Flow.
264
+
265
+ When the workflow completes, your web server has sent data to Shopify Flow because of the trigger. Shopify Flow has sent this data to a web server that logged the information to its console because of the action.
266
+
267
+ ## Step 6: Deploy your extension
268
+
269
+ > Note:
270
+ > Deploying extensions using the `app deploy` command also publishes the extensions. We recommend testing changes by using [`app dev`](/docs/api/shopify-cli/app/app-dev) or deploying to a test app before deploying them to a production app.
271
+
272
+ Use Shopify CLI to deploy your extensions:
273
+
274
+ 1. Navigate to your app directory.
275
+ 2. Run the following command to start deploying your extension(s):
276
+
277
+ ```bash
278
+ #!/bin/bash
279
+ shopify app deploy
280
+ ```
281
+
282
+ 3. Follow the prompts.
283
+
284
+ When you receive confirmation that the deploy was successful, your extensions have been released.
285
+
286
+
287
+ ## Verifying requests
288
+
289
+ For security reasons, make sure that you verify the following elements in each request:
290
+
291
+ - The POST request's HMAC header (either `x-shopify-hmac-sha256` or `http-x-shopify-hmac-sha256`). The HMAC header should be verified before you process the payload. For more information, refer to [Verifying requests](/docs/apps/build/flow/actions/endpoints#verifying-requests).
292
+ - The payload `handle`. This ID should match the `handle` of the action that you created, and can be retrieved from the payload preview.
293
+
294
+ ## Next steps
295
+
296
+ - Connect your app to Shopify Flow so that events that occur in your app can [trigger workflows](/docs/apps/build/flow/triggers).
297
+ - Learn how to receive [lifecycle events from Shopify Flow](/docs/apps/build/flow/track-lifecycle-events) about the stores that are using your triggers in enabled workflows.
298
+ - Learn more about how to [return complex data](/docs/apps/build/flow/configure-complex-data-types) in a Flow action.
data/scraped/raw/flow_actions_endpoints.txt ADDED
@@ -0,0 +1,667 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ Before your app can receive communication from Flow actions, you need to create one or more standardized API endpoints on your web server. Review the information for each endpoint to understand its requirements, the format of the payload, and the expected response. You'll also learn how to avoid processing duplicate requests, identify an action by its ID, and verify requests for security purposes.
4
+
5
+ | Endpoint | Purpose |
6
+ | --- | --- |
7
+ | [Flow action execution](/docs/apps/flow/actions/endpoints#flow-action-execution) | The endpoint where the automation tool sends your action's payload. The payload contains data that you can use to execute the action in your app.|
8
+ | [Custom configuration page preview](/docs/apps/flow/actions/endpoints#custom-configuration-page-preview) | An endpoint that provides data about your [custom configuration page](/docs/apps/build/flow/actions/build-config-ui) to display in the automation tool. This endpoint is required if you want to use a custom configuration page.|
9
+ | [Custom validation](/docs/apps/flow/actions/endpoints#custom-validation) | An endpoint that validates the contents of merchant-configurable properties in an action payload when an action is saved. This endpoint is required if you want to use a custom configuration page.|
10
+
11
+
12
+
13
+ ## General endpoint requirements
14
+
15
+ The requirements for Shopify Flow action endpoints are as follows:
16
+
17
+ | Rule / concern | Type / requirement |
18
+ | --- | --- |
19
+ | API format | REST |
20
+ | Content type | JSON |
21
+ | Security mechanism | [HMAC / Signed requests](#verifying-requests) |
22
+ | Protocol | HTTPS (app domain requires valid SSL certificate) |
23
+
24
+
25
+ ## Flow action execution
26
+
27
+ When a workflow that contains your action is executed, Flow sends an HTTP request to your Flow action execution endpoint (runtime URL). The request contains a payload that matches the payload schema that you configured for your action.
28
+
29
+ ### Request
30
+
31
+
32
+ <p>
33
+ <div class="react-code-block" data-preset="file">
34
+ <div class="react-code-block-preload ThemeMode-dim">
35
+ <div class="react-code-block-preload-bar "></div>
36
+ <div class="react-code-block-preload-placeholder-container">
37
+ <div class="react-code-block-preload-code-container">
38
+ <div class="react-code-block-preload-codeline-number"></div>
39
+ <div class="react-code-block-preload-codeline"></div>
40
+ </div>
41
+ <div class="react-code-block-preload-code-container">
42
+ <div class="react-code-block-preload-codeline-number"></div>
43
+ <div class="react-code-block-preload-codeline"></div>
44
+ </div>
45
+ <div class="react-code-block-preload-code-container">
46
+ <div class="react-code-block-preload-codeline-number"></div>
47
+ <div class="react-code-block-preload-codeline"></div>
48
+ </div>
49
+ <div class="react-code-block-preload-code-container">
50
+ <div class="react-code-block-preload-codeline-number"></div>
51
+ <div class="react-code-block-preload-codeline"></div>
52
+ </div>
53
+ <div class="react-code-block-preload-code-container">
54
+ <div class="react-code-block-preload-codeline-number"></div>
55
+ <div class="react-code-block-preload-codeline"></div>
56
+ </div>
57
+ <div class="react-code-block-preload-code-container">
58
+ <div class="react-code-block-preload-codeline-number"></div>
59
+ <div class="react-code-block-preload-codeline"></div>
60
+ </div>
61
+ <div class="react-code-block-preload-code-container">
62
+ <div class="react-code-block-preload-codeline-number"></div>
63
+ <div class="react-code-block-preload-codeline"></div>
64
+ </div>
65
+ <div class="react-code-block-preload-code-container">
66
+ <div class="react-code-block-preload-codeline-number"></div>
67
+ <div class="react-code-block-preload-codeline"></div>
68
+ </div>
69
+ <div class="react-code-block-preload-code-container">
70
+ <div class="react-code-block-preload-codeline-number"></div>
71
+ <div class="react-code-block-preload-codeline"></div>
72
+ </div>
73
+ <div class="react-code-block-preload-code-container">
74
+ <div class="react-code-block-preload-codeline-number"></div>
75
+ <div class="react-code-block-preload-codeline"></div>
76
+ </div>
77
+ <div class="react-code-block-preload-code-container">
78
+ <div class="react-code-block-preload-codeline-number"></div>
79
+ <div class="react-code-block-preload-codeline"></div>
80
+ </div>
81
+ <div class="react-code-block-preload-code-container">
82
+ <div class="react-code-block-preload-codeline-number"></div>
83
+ <div class="react-code-block-preload-codeline"></div>
84
+ </div>
85
+
86
+ </div>
87
+ </div>
88
+
89
+ <script data-option="filename" data-value="POST <Flow action HTTPS request URL>"></script>
90
+
91
+ <script type="text/plain" data-language="json">
92
+ {
93
+ "shop_id": "gid://shopify/Shop/1",
94
+ "shopify_domain": "{shop}.myshopify.com",
95
+ "action_run_id": "xxxx-xxxx-xxxx-xxxx",
96
+ "action_definition_id": "Place auction bid",
97
+ "handle": "place-auction-bid",
98
+ "properties": {
99
+ "customer_id": "123456",
100
+ "amount": "10.00",
101
+ "step_reference": "320d4f8a-aaab-40ff-9ed2-2bc079633705"
102
+ }
103
+ }
104
+ </script>
105
+
106
+ </div>
107
+ </p>
108
+
109
+
110
+
111
+ The payload contains the following parameters:
112
+
113
+ | Property Name | Property Usage |
114
+ | ------------------- | ------------------------------------------------------------------------------------------------------ |
115
+ | `shop_id` | The ID of the store. |
116
+ | `shopify_domain` | The myshopify.com domain of the store. |
117
+ | `action_run_id` | An ID that represents an instance of an action being run. [Learn more](#prevent-apps-from-processing-duplicate-requests). |
118
+ | `handle` | The extension’s handle. We recommend using this property to identify your actions. |
119
+ | `step_reference` | A unique ID for the step within a workflow. This property only appears if you’ve set a [Custom Configuration Page](/docs/apps/build/flow/actions/build-config-ui). |
120
+ | `action_definition_id` | A unique ID for the action. The ID is based on the action name in the Partner Dashboard. | |
121
+ | `properties` | The fields that you selected as part of the action configuration. |
122
+
123
+ To learn how to configure the payload schema, refer to [Shopify Flow actions](/docs/apps/build/flow/actions).
124
+
125
+ ### Expected response
126
+
127
+ After the automation tool sends a POST request to your web server, it waits for a maximum of 10 seconds for an [HTTP status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes).
128
+
129
+ If after 10 seconds the automation tool hasn't received a response from your web server, then the automation tool closes the connection to your web server and resends the request later.
130
+
131
+ When the automation tool receives a response, it processes the codes as displayed in the following table:
132
+
133
+ <table>
134
+ <tr>
135
+ <th>Status codes</th>
136
+ <th>Description</th>
137
+ </tr>
138
+ <tr>
139
+ <td>200 Success</td>
140
+ <td>The automation tool assumes that the POST request has been processed by your web server.</td>
141
+ </tr>
142
+ <tr>
143
+ <td>202 Success</td>
144
+ <td>The automation tool assumes that the POST request has been accepted but not processed by your web server. The automation tool will resend the POST request at increasing intervals for up to 36 hours.
145
+ </td>
146
+ </tr>
147
+ <tr>
148
+ <td>4XX Client errors</td>
149
+ <td>
150
+ <p>If your web server sends a 429 status code without a <code>Retry-After</code> header, then the automation tool resends the POST request at increasing intervals for up to 36 hours.</p>
151
+ <p>If your web server sends a 429 status code with a <code>Retry-After</code> header that specifies a wait time, then the automation tool resends the POST request after the wait time (formatted in seconds) has passed.<p>
152
+ <p>If your web server sends any other 4XX code, then the automation tool assumes that there was a failure and it doesn't resend the POST request. Merchants see a notification in the automation tool that includes the raw contents of your web server's response.</p>
153
+ <p><strong>Example</strong>: <code>400 Bad Request { "error1": "server unresponsive" }</code></p>
154
+ <p>You can provide a merchant-friendly description of the error by adding a key named <code>message</code>. For example:</p>
155
+ <p><strong>Example</strong>: <code>{ "message": "Finish the onboarding on our website." }</code>
156
+ </td>
157
+ </tr>
158
+ <tr>
159
+ <td>5XX Server errors</td>
160
+ <td>The automation tool resends the POST request at increasing intervals for up to 36 hours.</td>
161
+ </tr>
162
+ <tr>
163
+ <td>Other status code</td>
164
+ <td>If your web server returns a code that isn't described in this table, then the automation tool assumes that there was a failure and it doesn't resend the POST request.</td>
165
+ </tr>
166
+ </table>
167
+
168
+ ### Prevent apps from processing duplicate requests
169
+
170
+ Each request from an automation workflow contains an `action_run_id` that's unique to the associated action run. This ID is included in the body of the request.
171
+
172
+ You can use `action_run_id` as an [idempotency key](/docs/api/usage/idempotent-requests) to check if the request is unique. In some cases, your app could receive an identical request more than once. For example, the automation tool might resend a request because it didn't receive your response in time. Your app can store the idempotency key in a cache with a set expiry time to avoid reprocessing duplicate requests.
173
+
174
+ ### Identify actions
175
+
176
+ The `handle` property is how you identify the action for processing when your web server receives a request from Flow during workflow execution.
177
+
178
+ ```json
179
+ {
180
+ "shop_id": 0,
181
+ "shopify_domain": "{shop}.myshopify.com",
182
+ "action_run_id": "xxxx-xxxx-xxxx-xxxx",
183
+ "handle": "auction-bid",
184
+ "action_definition_id": "Auction Bid",
185
+ "properties": {}
186
+ }
187
+ ```
188
+
189
+
190
+ ## Custom configuration page preview
191
+
192
+ An endpoint that provides data about your [custom configuration page](/docs/apps/build/flow/actions/build-config-ui) to display in the automation tool. This endpoint is required if you want to use a custom configuration page. Using the endpoint, you can dynamically set the following information:
193
+
194
+ - The field’s label
195
+ - A text preview
196
+ - A last updated at timestamp
197
+ - An image preview
198
+ - The text used by the button that redirects to the custom configuration page
199
+
200
+ ### Request
201
+
202
+ <p>
203
+ <div class="react-code-block" data-preset="file">
204
+ <div class="react-code-block-preload ThemeMode-dim">
205
+ <div class="react-code-block-preload-bar "></div>
206
+ <div class="react-code-block-preload-placeholder-container">
207
+ <div class="react-code-block-preload-code-container">
208
+ <div class="react-code-block-preload-codeline-number"></div>
209
+ <div class="react-code-block-preload-codeline"></div>
210
+ </div>
211
+ <div class="react-code-block-preload-code-container">
212
+ <div class="react-code-block-preload-codeline-number"></div>
213
+ <div class="react-code-block-preload-codeline"></div>
214
+ </div>
215
+ <div class="react-code-block-preload-code-container">
216
+ <div class="react-code-block-preload-codeline-number"></div>
217
+ <div class="react-code-block-preload-codeline"></div>
218
+ </div>
219
+ <div class="react-code-block-preload-code-container">
220
+ <div class="react-code-block-preload-codeline-number"></div>
221
+ <div class="react-code-block-preload-codeline"></div>
222
+ </div>
223
+ <div class="react-code-block-preload-code-container">
224
+ <div class="react-code-block-preload-codeline-number"></div>
225
+ <div class="react-code-block-preload-codeline"></div>
226
+ </div>
227
+ <div class="react-code-block-preload-code-container">
228
+ <div class="react-code-block-preload-codeline-number"></div>
229
+ <div class="react-code-block-preload-codeline"></div>
230
+ </div>
231
+ <div class="react-code-block-preload-code-container">
232
+ <div class="react-code-block-preload-codeline-number"></div>
233
+ <div class="react-code-block-preload-codeline"></div>
234
+ </div>
235
+ <div class="react-code-block-preload-code-container">
236
+ <div class="react-code-block-preload-codeline-number"></div>
237
+ <div class="react-code-block-preload-codeline"></div>
238
+ </div>
239
+ <div class="react-code-block-preload-code-container">
240
+ <div class="react-code-block-preload-codeline-number"></div>
241
+ <div class="react-code-block-preload-codeline"></div>
242
+ </div>
243
+ <div class="react-code-block-preload-code-container">
244
+ <div class="react-code-block-preload-codeline-number"></div>
245
+ <div class="react-code-block-preload-codeline"></div>
246
+ </div>
247
+ <div class="react-code-block-preload-code-container">
248
+ <div class="react-code-block-preload-codeline-number"></div>
249
+ <div class="react-code-block-preload-codeline"></div>
250
+ </div>
251
+ <div class="react-code-block-preload-code-container">
252
+ <div class="react-code-block-preload-codeline-number"></div>
253
+ <div class="react-code-block-preload-codeline"></div>
254
+ </div>
255
+
256
+ </div>
257
+ </div>
258
+
259
+ <script data-option="filename" data-value="POST <Custom configuration page preview URL>"></script>
260
+
261
+ <script type="text/plain" data-language="json">
262
+ {
263
+ "shop_id": "gid://shopify/Shop/1",
264
+ "shopify_domain": "{shop}.myshopify.com",
265
+ "step_reference": "122438de2e57d8bad7e50958d2bd4999ca2c4c35ee3b5120e85e42a17fc1ce93",
266
+ "handle": "my-extension-handle",
267
+ "locale":"en",
268
+ "properties": {
269
+ "customer_id": "gid://shopify/Customer/1234567",
270
+ "sms_message": "Thanks for making the purchase!",
271
+ "marketing_activity_id": "gid://shopify/MarketingActivity/1234567"
272
+ }
273
+ }
274
+ </script>
275
+
276
+ </div>
277
+ </p>
278
+
279
+
280
+ The payload contains the following parameters:
281
+
282
+ | Parameter | Description |
283
+ | ---------------------- | --- |
284
+ | `shop_id` | The ID of the store. |
285
+ | `shopify_domain` | The myshopify.com domain of the store. |
286
+ | `handle` | The extension’s handle. We recommend using this property to identify your actions. |
287
+ | `step_reference` | A unique ID for the step within a workflow. |
288
+ | `locale` | The locale of the store making the request, in ISO format. |
289
+ | `properties` | The fields that you selected as part of the action configuration. |
290
+
291
+ ### Expected response
292
+
293
+ ```json
294
+ {
295
+ "label_text": "Abandonment Email Template",
296
+ "text_preview": "We want you back. Enjoy a 15% discount on your next purchase.",
297
+ "button_text": "Edit Email",
298
+ "image_preview": {
299
+ "url": "http://someUrl.io/assets/preview_image.png",
300
+ "alt": "Abandonment Email Template Preview Image"
301
+ },
302
+ "last_updated_at": "2023-02-10T16:50:24.709Z"
303
+ }
304
+
305
+ ```
306
+
307
+ Other than `text_preview`, all fields are nullable.
308
+
309
+ <table>
310
+   <caption></caption>
311
+   <thead>
312
+     <tr>
313
+       <th scope=“col”>Parameter</th>
314
+       <th scope=“col”>Description</th>
315
+     </tr>
316
+   </thead>
317
+   <tbody>
318
+     <tr>
319
+ <td scope=“row”>1</td>
320
+       <td><code>label_text</code></td>
321
+       <td>A title for the custom configuration page.<br><br>If no value is specified, then the label text defaults to <b>Configuration Page Preview</b>.</td>
322
+     </tr>
323
+     <tr>
324
+ <td scope=“row”>2</td>
325
+       <td><code>text_preview</code></td>
326
+       <td>A preview that indicates the resource that's tied to the step. For example, in the case of an email content editor, this might be a preview of the email text.<br><br>This field is required.</td>
327
+     </tr>
328
+     <tr>
329
+ <td scope=“row”>3</td>
330
+       <td><code>button_text</code></td>
331
+       <td>The text for the button that the merchant clicks to access the custom configuration page.<br><br>If no value is specified, then the label text defaults to <b>Edit<b>.<br><br>If the value for `button_text` is longer than 23 characters, then the label is truncated to twenty characters with an ellipsis.</td>
332
+     </tr>
333
+     <tr>
334
+ <td scope=“row”></td>
335
+       <td><code>image_preview</code></td>
336
+       <td>The details of the image.</td>
337
+     </tr>
338
+     <tr>
339
+ <td scope=“row”>4</td>
340
+       <td><code>image_preview.url</code></td>
341
+       <td>The URL for a preview image of the custom configuration page. The image should be between 500px and 600px wide, and 100KB or less. There is no maximum height.</td>
342
+     </tr>
343
+     <tr>
344
+ <td scope=“row”></td>
345
+       <td><code>image_preview.thumbnail_url</code></td>
346
+       <td>The URL for a thumbnail version of the preview image.<br><br>This image is not currently used in the user interface.</td>
347
+     </tr>
348
+     <tr>
349
+ <td scope=“row”></td>
350
+       <td><code>image_preview.alt</code></td>
351
+       <td>The alt text for the preview image. This text appears if your image fails to render, and is accessible to screen readers.</td>
352
+     </tr>
353
+     <tr>
354
+ <td scope=“row”>5</td>
355
+       <td><code>last_updated_at</code></td>
356
+       <td>The date and time that the resource was last updated, in <a href="https://en.wikipedia.org/wiki/ISO_8601">IS0-8601</a> format.</td>
357
+     </tr>
358
+   </tbody>
359
+ </table>
360
+
361
+ <figure class="figure"><img src="https://cdn.shopify.com/shopifycloud/shopify_dev/assets/apps/flow/ccp-preview-annotated-379253a9b1eebe09194a0a0a0e5be1e2fd918fc977bdd1f78db60fa6f1e119c3.png" class="lazyload" alt="A labeled custom configuration page." width="901" height="675"></figure>
362
+
363
+
364
+ ## Custom validation
365
+
366
+ An endpoint that validates the contents of merchant-configurable properties in an action payload when an action is saved. This endpoint is required if you want to use a custom configuration page.
367
+
368
+ ### Request
369
+
370
+ The request contains a payload that matches the payload schema you configured for your action.
371
+
372
+ <p>
373
+ <div class="react-code-block" data-preset="file">
374
+ <div class="react-code-block-preload ThemeMode-dim">
375
+ <div class="react-code-block-preload-bar "></div>
376
+ <div class="react-code-block-preload-placeholder-container">
377
+ <div class="react-code-block-preload-code-container">
378
+ <div class="react-code-block-preload-codeline-number"></div>
379
+ <div class="react-code-block-preload-codeline"></div>
380
+ </div>
381
+ <div class="react-code-block-preload-code-container">
382
+ <div class="react-code-block-preload-codeline-number"></div>
383
+ <div class="react-code-block-preload-codeline"></div>
384
+ </div>
385
+ <div class="react-code-block-preload-code-container">
386
+ <div class="react-code-block-preload-codeline-number"></div>
387
+ <div class="react-code-block-preload-codeline"></div>
388
+ </div>
389
+ <div class="react-code-block-preload-code-container">
390
+ <div class="react-code-block-preload-codeline-number"></div>
391
+ <div class="react-code-block-preload-codeline"></div>
392
+ </div>
393
+ <div class="react-code-block-preload-code-container">
394
+ <div class="react-code-block-preload-codeline-number"></div>
395
+ <div class="react-code-block-preload-codeline"></div>
396
+ </div>
397
+ <div class="react-code-block-preload-code-container">
398
+ <div class="react-code-block-preload-codeline-number"></div>
399
+ <div class="react-code-block-preload-codeline"></div>
400
+ </div>
401
+ <div class="react-code-block-preload-code-container">
402
+ <div class="react-code-block-preload-codeline-number"></div>
403
+ <div class="react-code-block-preload-codeline"></div>
404
+ </div>
405
+ <div class="react-code-block-preload-code-container">
406
+ <div class="react-code-block-preload-codeline-number"></div>
407
+ <div class="react-code-block-preload-codeline"></div>
408
+ </div>
409
+ <div class="react-code-block-preload-code-container">
410
+ <div class="react-code-block-preload-codeline-number"></div>
411
+ <div class="react-code-block-preload-codeline"></div>
412
+ </div>
413
+ <div class="react-code-block-preload-code-container">
414
+ <div class="react-code-block-preload-codeline-number"></div>
415
+ <div class="react-code-block-preload-codeline"></div>
416
+ </div>
417
+ <div class="react-code-block-preload-code-container">
418
+ <div class="react-code-block-preload-codeline-number"></div>
419
+ <div class="react-code-block-preload-codeline"></div>
420
+ </div>
421
+ <div class="react-code-block-preload-code-container">
422
+ <div class="react-code-block-preload-codeline-number"></div>
423
+ <div class="react-code-block-preload-codeline"></div>
424
+ </div>
425
+ <div class="react-code-block-preload-code-container">
426
+ <div class="react-code-block-preload-codeline-number"></div>
427
+ <div class="react-code-block-preload-codeline"></div>
428
+ </div>
429
+ <div class="react-code-block-preload-code-container">
430
+ <div class="react-code-block-preload-codeline-number"></div>
431
+ <div class="react-code-block-preload-codeline"></div>
432
+ </div>
433
+ <div class="react-code-block-preload-code-container">
434
+ <div class="react-code-block-preload-codeline-number"></div>
435
+ <div class="react-code-block-preload-codeline"></div>
436
+ </div>
437
+ <div class="react-code-block-preload-code-container">
438
+ <div class="react-code-block-preload-codeline-number"></div>
439
+ <div class="react-code-block-preload-codeline"></div>
440
+ </div>
441
+ <div class="react-code-block-preload-code-container">
442
+ <div class="react-code-block-preload-codeline-number"></div>
443
+ <div class="react-code-block-preload-codeline"></div>
444
+ </div>
445
+ <div class="react-code-block-preload-code-container">
446
+ <div class="react-code-block-preload-codeline-number"></div>
447
+ <div class="react-code-block-preload-codeline"></div>
448
+ </div>
449
+ <div class="react-code-block-preload-code-container">
450
+ <div class="react-code-block-preload-codeline-number"></div>
451
+ <div class="react-code-block-preload-codeline"></div>
452
+ </div>
453
+ <div class="react-code-block-preload-code-container">
454
+ <div class="react-code-block-preload-codeline-number"></div>
455
+ <div class="react-code-block-preload-codeline"></div>
456
+ </div>
457
+ <div class="react-code-block-preload-code-container">
458
+ <div class="react-code-block-preload-codeline-number"></div>
459
+ <div class="react-code-block-preload-codeline"></div>
460
+ </div>
461
+ <div class="react-code-block-preload-code-container">
462
+ <div class="react-code-block-preload-codeline-number"></div>
463
+ <div class="react-code-block-preload-codeline"></div>
464
+ </div>
465
+ <div class="react-code-block-preload-code-container">
466
+ <div class="react-code-block-preload-codeline-number"></div>
467
+ <div class="react-code-block-preload-codeline"></div>
468
+ </div>
469
+ <div class="react-code-block-preload-code-container">
470
+ <div class="react-code-block-preload-codeline-number"></div>
471
+ <div class="react-code-block-preload-codeline"></div>
472
+ </div>
473
+ <div class="react-code-block-preload-code-container">
474
+ <div class="react-code-block-preload-codeline-number"></div>
475
+ <div class="react-code-block-preload-codeline"></div>
476
+ </div>
477
+ <div class="react-code-block-preload-code-container">
478
+ <div class="react-code-block-preload-codeline-number"></div>
479
+ <div class="react-code-block-preload-codeline"></div>
480
+ </div>
481
+
482
+ </div>
483
+ </div>
484
+
485
+ <script data-option="filename" data-value="POST <Validation endpoint>"></script>
486
+
487
+ <script type="text/plain" data-language="json">
488
+ {
489
+ "shop_id": "gid://shopify/Shop/1",
490
+ "shopify_domain": "{shop}.myshopify.com",
491
+ "handle": "my-extension-handle",
492
+ "locale": "en",
493
+ "steps": [
494
+ {
495
+ "step_reference": "122438de2e57d8bad7e50958d2bd4999ca2c4c35ee3b5120e85e42a17fc1ce93",
496
+ "properties" : {
497
+ "outside_na": true,
498
+ "guest_no": 22,
499
+ "first_name": "John",
500
+ "customer_id": "customer.id"
501
+ }
502
+ },
503
+ {
504
+ "step_reference": "ca2c4c35ee3b5120e85e42a17fc1ce93122438de2e57d8bad7e50958d2bd4999",
505
+ "properties" : {
506
+ "outside_na": false,
507
+ "guest_no": 14,
508
+ "first_name": "Kim",
509
+ "customer_id": "customer.id"
510
+ }
511
+ },
512
+ ]
513
+ }
514
+
515
+ </script>
516
+
517
+ </div>
518
+ </p>
519
+
520
+
521
+ The payload contains the following parameters:
522
+
523
+ <table>
524
+   <caption></caption>
525
+   <thead>
526
+     <tr>
527
+       <th scope=“col”>Parameter</th>
528
+       <th scope=“col”>Description</th>
529
+     </tr>
530
+   </thead>
531
+   <tbody>
532
+     <tr>
533
+       <td scope=“row”><code>shop_id</code></td>
534
+       <td>The ID of the store.</td>
535
+     </tr>
536
+     <tr>
537
+       <td scope=“row”><code>shopify_domain</code></td>
538
+       <td>The myshopify.com domain of the store.</td>
539
+     </tr>
540
+     <tr>
541
+       <td scope=“row”><code>handle</code></td>
542
+       <td>The extension’s handle. We recommend using this property to identify your actions.</td>
543
+     </tr>
544
+     <tr>
545
+       <td scope=“row”><code>locale</code></td>
546
+       <td>The locale of the store, in ISO format.</td>
547
+     </tr>
548
+     <tr>
549
+       <td scope=“row”><code>steps</code></td>
550
+       <td>An array of all of the steps to validate. Each child step object represents a separate action on the merchant’s workflow.</td>
551
+     </tr>
552
+     <tr>
553
+       <td scope=“row”><code>steps.step_reference</code></td>
554
+       <td>The unique identifier for the step. This ID should be used when returning errors for a step.</td>
555
+     </tr>
556
+     <tr>
557
+       <td scope=“row”><code>steps.properties</code></td>
558
+       <td>
559
+ <p>An object containing the properties specified on the action.</p>
560
+ <p><b>Merchant-configurable properties</b>: These properties are passed as strings, with the following exceptions:</p>
561
+ <ul>
562
+ <li>Checkbox properties: Boolean</li>
563
+ <li>Number properties: integer</li>
564
+ </ul>
565
+ <p><b>Shopify properties</b>:
566
+ The path to the value for the related commerce object in the workflow environment. For example, <code>customer.id</code>. If the value isn't available in the workflow environment, then an empty string is returned. The property will be populated with an actual value at runtime.</p>
567
+ <p><b>Example 1: Customer ID is available in the workflow environment</b></p>
568
+ <ul>
569
+ <li>Validation payload value: "customer.id"</li>
570
+ <li>Runtime value: "123456"</li>
571
+ </ul>
572
+ <p><b>Example 2: Customer ID isn't available in the workflow environment</b></p>
573
+ <ul>
574
+ <li>Validation payload value: ""</li>
575
+ <li>Runtime value: null</li>
576
+ </ul>
577
+ <p>If a property is marked as optional, then the workflow tool won't validate the presence of the commerce object, and will only rely on external validation. The path to the value for the commerce objects is still returned as a path, but Shopify can't guarantee their presence at runtime. If you need a commerce object to be present at runtime, then you should mark it as required. This allows the workflow tool to assess the presence of the commerce object and return any errors to the editor.</p>
578
+ <p><b>Example 3: Customer ID might be available in the workflow environment (for example, when using a custom trigger and an order step)</b></p>
579
+ <ul>
580
+ <li>Validation payload value: "customer.lastOrder.id"</li>
581
+ <li>Runtime value: "123456" OR null</li>
582
+ </ul>
583
+
584
+ </td>
585
+     </tr>
586
+   </tbody>
587
+ </table>
588
+
589
+ ### Expected response
590
+
591
+ Your app should return an array of the steps that you validated, which are identified by their `step_reference`. If there are any validation errors, then specify them in a `step_errors` array. The error messages that return display to the merchant in the action configuration pane in Shopify Flow.
592
+
593
+ ![An image of error messages in the action configuration pane.](/assets/apps/flow/validation-error.png)
594
+
595
+ ```yml
596
+ [
597
+ {
598
+ step_reference: '122438de2e57d8bad7e50958d2bd4999ca2c4c35ee3b5120e85e42a17fc1ce93',
599
+ step_errors: [
600
+ {
601
+ message: 'A step level error occurred'
602
+ }
603
+ ],
604
+ properties_errors: [
605
+ {
606
+ id: 'guest_no',
607
+ message: 'Number of guests is limited to 8 when outside of North America'
608
+ }
609
+ ]
610
+ },
611
+ {
612
+ step_reference: 'ca2c4c35ee3b5120e85e42a17fc1ce93122438de2e57d8bad7e50958d2bd4999',
613
+ step_errors: [],
614
+ properties_errors: []
615
+ }
616
+ ]
617
+ ```
618
+
619
+ <table>
620
+   <caption></caption>
621
+   <thead>
622
+     <tr>
623
+       <th scope=“col”>Parameter</th>
624
+       <th scope=“col”>Description</th>
625
+     </tr>
626
+   </thead>
627
+   <tbody>
628
+     <tr>
629
+       <td scope=“row”><code>step_reference</code></td>
630
+       <td>The unique identifier for the step. This ID should be used when returning errors for a step.</td>
631
+     </tr>
632
+     <tr>
633
+       <td scope=“row”><code>step_errors</code></td>
634
+       <td>An array of errors that apply to the entire step.</td>
635
+     </tr>
636
+     <tr>
637
+       <td scope=“row”><code>step_errors.message</code></td>
638
+       <td>An error message to display at the top of the action configuration pane.</td>
639
+     </tr>
640
+     <tr>
641
+       <td scope=“row”><code>properties_errors</code></td>
642
+       <td>An array of errors that apply to particular properties.</td>
643
+     </tr>
644
+     <tr>
645
+       <td scope=“row”><code>properties_errors.id</code></td>
646
+       <td>The key of the property that contains the error.</td>
647
+     </tr>
648
+     <tr>
649
+       <td scope=“row”><code>properties_errors.message</code></td>
650
+       <td>An error message to display for the property.</td>
651
+     </tr>
652
+   </tbody>
653
+ </table>
654
+
655
+
656
+ ## Verifying requests
657
+
658
+ For security reasons, your web service should enforce a hash-based message authentication (HMAC) header verification that uses the client secret that you created when you configured your app.
659
+
660
+ The name of the HMAC header is `x-shopify-hmac-sha256`. If you are using a Ruby-based web framework, then the name of the header is `http-x-shopify-hmac-sha256`.
661
+
662
+ When the action runs in a workflow, the automation tool posts the contents (JSON payload and the HMAC header) of the action to the URL that you entered when you created the action in the Partner Dashboard. When your web server receives the POST request, it needs to verify the HMAC header against the JSON payload and your app's API secret. The HMAC verification works the same as [webhooks](/docs/apps/build/webhooks/subscribe/https).
663
+
664
+ Your web server also needs to [verify that the `handle` that's sent in the payload matches the `handle` of the action that you created](#identify-actions).
665
+
666
+ After you've verified the HMAC header, you can process the contents of the payload. For example, you could log the contents of the payload to your web server's console.
667
+
data/scraped/raw/flow_configure-complex-data-types.txt ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ Triggers and actions can both provide data to Flow workflows. This data can be simple, such as a string or a number, or complex, such as an object or a list of objects. This guide explains how to define complex data types in your extension's TOML and how to send and receive complex data types at runtime.
4
+
5
+ ## Defining a return type schema
6
+
7
+ To return data from an action or complex objects from a trigger, you must provide a schema for the return type using GraphQL's type system ([SDL](https://graphql.org/learn/schema/#type-language)). This schema is used by Flow to provide the return object in the workflow editor. The schema can be defined in any file and linked to from your extension's TOML definition. For example, a file called `schema.graphql` which contains the SDL for the types used in your action or trigger, can be made in the same directory as the extension.
8
+
9
+ ### SDL file
10
+
11
+ When you're using complex types in Flow actions and triggers, consider the following:
12
+
13
+ - Flow supports defining types using basic types (String, Int, Float, Boolean, and ID) as well as enums, objects, lists, and the non-nullable flag `!`.
14
+ - Flow doesn't currently support the entire SDL spec when defining action return types. Unions, interfaces, custom scalars, and directives are currently not supported. The action HTTP payload doesn't utilize any arguments defined on types in this schema.
15
+ - Flow derives the description of the return value from the comment on the type, which is placed in double quotes above the field. This description displays to merchants in the Flow editor when selecting the field.
16
+ - The same schema file can be referenced by multiple extensions as long as the relative paths are defined correctly.
17
+
18
+ The following SDL defines two types: a `Bid` and an `Auction` which contains a list of bids. The schema can contain multiple types that reference each other but only one type can be defined as the return type for the action. In the following example we're referencing the `Bid` type in the `Auction` type.
19
+
20
+ <p>
21
+ <div class="react-code-block" data-preset="file">
22
+ <div class="react-code-block-preload ThemeMode-dim">
23
+ <div class="react-code-block-preload-bar "></div>
24
+ <div class="react-code-block-preload-placeholder-container">
25
+ <div class="react-code-block-preload-code-container">
26
+ <div class="react-code-block-preload-codeline-number"></div>
27
+ <div class="react-code-block-preload-codeline"></div>
28
+ </div>
29
+ <div class="react-code-block-preload-code-container">
30
+ <div class="react-code-block-preload-codeline-number"></div>
31
+ <div class="react-code-block-preload-codeline"></div>
32
+ </div>
33
+ <div class="react-code-block-preload-code-container">
34
+ <div class="react-code-block-preload-codeline-number"></div>
35
+ <div class="react-code-block-preload-codeline"></div>
36
+ </div>
37
+ <div class="react-code-block-preload-code-container">
38
+ <div class="react-code-block-preload-codeline-number"></div>
39
+ <div class="react-code-block-preload-codeline"></div>
40
+ </div>
41
+ <div class="react-code-block-preload-code-container">
42
+ <div class="react-code-block-preload-codeline-number"></div>
43
+ <div class="react-code-block-preload-codeline"></div>
44
+ </div>
45
+ <div class="react-code-block-preload-code-container">
46
+ <div class="react-code-block-preload-codeline-number"></div>
47
+ <div class="react-code-block-preload-codeline"></div>
48
+ </div>
49
+ <div class="react-code-block-preload-code-container">
50
+ <div class="react-code-block-preload-codeline-number"></div>
51
+ <div class="react-code-block-preload-codeline"></div>
52
+ </div>
53
+ <div class="react-code-block-preload-code-container">
54
+ <div class="react-code-block-preload-codeline-number"></div>
55
+ <div class="react-code-block-preload-codeline"></div>
56
+ </div>
57
+ <div class="react-code-block-preload-code-container">
58
+ <div class="react-code-block-preload-codeline-number"></div>
59
+ <div class="react-code-block-preload-codeline"></div>
60
+ </div>
61
+ <div class="react-code-block-preload-code-container">
62
+ <div class="react-code-block-preload-codeline-number"></div>
63
+ <div class="react-code-block-preload-codeline"></div>
64
+ </div>
65
+ <div class="react-code-block-preload-code-container">
66
+ <div class="react-code-block-preload-codeline-number"></div>
67
+ <div class="react-code-block-preload-codeline"></div>
68
+ </div>
69
+ <div class="react-code-block-preload-code-container">
70
+ <div class="react-code-block-preload-codeline-number"></div>
71
+ <div class="react-code-block-preload-codeline"></div>
72
+ </div>
73
+ <div class="react-code-block-preload-code-container">
74
+ <div class="react-code-block-preload-codeline-number"></div>
75
+ <div class="react-code-block-preload-codeline"></div>
76
+ </div>
77
+ <div class="react-code-block-preload-code-container">
78
+ <div class="react-code-block-preload-codeline-number"></div>
79
+ <div class="react-code-block-preload-codeline"></div>
80
+ </div>
81
+ <div class="react-code-block-preload-code-container">
82
+ <div class="react-code-block-preload-codeline-number"></div>
83
+ <div class="react-code-block-preload-codeline"></div>
84
+ </div>
85
+ <div class="react-code-block-preload-code-container">
86
+ <div class="react-code-block-preload-codeline-number"></div>
87
+ <div class="react-code-block-preload-codeline"></div>
88
+ </div>
89
+ <div class="react-code-block-preload-code-container">
90
+ <div class="react-code-block-preload-codeline-number"></div>
91
+ <div class="react-code-block-preload-codeline"></div>
92
+ </div>
93
+ <div class="react-code-block-preload-code-container">
94
+ <div class="react-code-block-preload-codeline-number"></div>
95
+ <div class="react-code-block-preload-codeline"></div>
96
+ </div>
97
+ <div class="react-code-block-preload-code-container">
98
+ <div class="react-code-block-preload-codeline-number"></div>
99
+ <div class="react-code-block-preload-codeline"></div>
100
+ </div>
101
+ <div class="react-code-block-preload-code-container">
102
+ <div class="react-code-block-preload-codeline-number"></div>
103
+ <div class="react-code-block-preload-codeline"></div>
104
+ </div>
105
+ <div class="react-code-block-preload-code-container">
106
+ <div class="react-code-block-preload-codeline-number"></div>
107
+ <div class="react-code-block-preload-codeline"></div>
108
+ </div>
109
+ <div class="react-code-block-preload-code-container">
110
+ <div class="react-code-block-preload-codeline-number"></div>
111
+ <div class="react-code-block-preload-codeline"></div>
112
+ </div>
113
+ <div class="react-code-block-preload-code-container">
114
+ <div class="react-code-block-preload-codeline-number"></div>
115
+ <div class="react-code-block-preload-codeline"></div>
116
+ </div>
117
+ <div class="react-code-block-preload-code-container">
118
+ <div class="react-code-block-preload-codeline-number"></div>
119
+ <div class="react-code-block-preload-codeline"></div>
120
+ </div>
121
+ <div class="react-code-block-preload-code-container">
122
+ <div class="react-code-block-preload-codeline-number"></div>
123
+ <div class="react-code-block-preload-codeline"></div>
124
+ </div>
125
+ <div class="react-code-block-preload-code-container">
126
+ <div class="react-code-block-preload-codeline-number"></div>
127
+ <div class="react-code-block-preload-codeline"></div>
128
+ </div>
129
+ <div class="react-code-block-preload-code-container">
130
+ <div class="react-code-block-preload-codeline-number"></div>
131
+ <div class="react-code-block-preload-codeline"></div>
132
+ </div>
133
+
134
+ </div>
135
+ </div>
136
+
137
+
138
+ <script type="text/plain" data-language="graphql">
139
+ RAW_MD_CONTENT"Represents a bid placed on an auction"
140
+ type Bid {
141
+ "ID of the bid"
142
+ id: ID!
143
+ "Customer that placed the bid"
144
+ customerId: ID!
145
+ "Amount of the bid"
146
+ amount: Float!
147
+ }
148
+
149
+ enum Status {
150
+ COMPLETE
151
+ IN_PROGRESS
152
+ CANCELLED
153
+ }
154
+
155
+ "Represents an auction"
156
+ type Auction {
157
+ "ID of the auction"
158
+ id: ID!
159
+ "Name of the auction"
160
+ name: String
161
+ "Status of the auction"
162
+ status: Status!
163
+ "List of bids placed on the auction"
164
+ bids: [Bid!]!
165
+ }
166
+ END_RAW_MD_CONTENT</script>
167
+
168
+ </div>
169
+ </p>
170
+
171
+
172
+ For more information on SDL, refer to the [GraphQL documentation](https://graphql.org/learn/schema/#type-language).
173
+
174
+ ### Folder structure
175
+
176
+ ```
177
+ /my-extension-name
178
+ shopify.extensions.toml
179
+ schema.graphql
180
+ ```
181
+
182
+ ### `shopify.extension.toml` file
183
+
184
+ <p>
185
+ <div class="react-code-block" data-preset="file">
186
+ <div class="react-code-block-preload ThemeMode-dim">
187
+ <div class="react-code-block-preload-bar "></div>
188
+ <div class="react-code-block-preload-placeholder-container">
189
+ <div class="react-code-block-preload-code-container">
190
+ <div class="react-code-block-preload-codeline-number"></div>
191
+ <div class="react-code-block-preload-codeline"></div>
192
+ </div>
193
+ <div class="react-code-block-preload-code-container">
194
+ <div class="react-code-block-preload-codeline-number"></div>
195
+ <div class="react-code-block-preload-codeline"></div>
196
+ </div>
197
+ <div class="react-code-block-preload-code-container">
198
+ <div class="react-code-block-preload-codeline-number"></div>
199
+ <div class="react-code-block-preload-codeline"></div>
200
+ </div>
201
+ <div class="react-code-block-preload-code-container">
202
+ <div class="react-code-block-preload-codeline-number"></div>
203
+ <div class="react-code-block-preload-codeline"></div>
204
+ </div>
205
+ <div class="react-code-block-preload-code-container">
206
+ <div class="react-code-block-preload-codeline-number"></div>
207
+ <div class="react-code-block-preload-codeline"></div>
208
+ </div>
209
+ <div class="react-code-block-preload-code-container">
210
+ <div class="react-code-block-preload-codeline-number"></div>
211
+ <div class="react-code-block-preload-codeline"></div>
212
+ </div>
213
+ <div class="react-code-block-preload-code-container">
214
+ <div class="react-code-block-preload-codeline-number"></div>
215
+ <div class="react-code-block-preload-codeline"></div>
216
+ </div>
217
+ <div class="react-code-block-preload-code-container">
218
+ <div class="react-code-block-preload-codeline-number"></div>
219
+ <div class="react-code-block-preload-codeline"></div>
220
+ </div>
221
+
222
+ </div>
223
+ </div>
224
+
225
+
226
+ <script type="text/plain" data-language="bash" data-title="toml">
227
+ RAW_MD_CONTENT[[extensions]]
228
+ name = "Place auction bid"
229
+ type = "flow_action"
230
+ handle = "auction-bid"
231
+ description = "My description"
232
+ runtime_url = "https://{url}.com/api/execute"
233
+ schema = "./schema.graphql"
234
+ return_type_ref = "Auction"
235
+ END_RAW_MD_CONTENT</script>
236
+
237
+ </div>
238
+ </p>
239
+
240
+
241
+ ## Referencing the return type schema in an action extension's TOML
242
+
243
+ After a schema file has been defined, it can be referenced in the action extension's TOML by setting `extensions.schema` to the relative path of the schema file, and `extension.return_type_ref` to a type defined in the referenced schema file. The schema defined above can be referenced by setting the following fields:
244
+
245
+ | Property Name | Property value |
246
+ | ------------------- | --------------- |
247
+ | `extensions.schema` | ./schema.graphql |
248
+ | `extensions.return_type_ref` | Auction |
249
+
250
+ ## Referencing the return type schema in a trigger extension's TOML
251
+
252
+ After a schema file has been defined, it can be referenced in the trigger extension's TOML by setting `extensions.schema` to the relative path of the schema file, and setting the type of a field to `schema.<type>`. The schema defined above can be referenced by setting the following fields:
253
+
254
+ | Property Name | Property value |
255
+ | ------------------- | --------------- |
256
+ | `extensions.schema` | ./schema.graphql |
257
+ | `extensions.settings.fields[0].type` | schema.Auction |
258
+
259
+ ## Returning data from an action at runtime
260
+
261
+ When responding to an action request from Flow you can add the return type in the JSON response as a field called `return_value`. The `return_value` object must match the return type defined in the extension. The return type used in our [example](#shopify-extension-toml-file) must be an auction object, like the following:
262
+
263
+ ```json
264
+ {
265
+ "return_value": {
266
+ "id": "auction1",
267
+ "name": "My first auction",
268
+ "status": "COMPLETE",
269
+ "bids": [
270
+ {
271
+ "id": "bid1",
272
+ "customerId": "gid://shopify/Customer/1",
273
+ "amount": 100.00
274
+ },
275
+ {
276
+ "id": "bid2",
277
+ "customerId": "gid://shopify/Customer/2",
278
+ "amount": 103.11
279
+ }
280
+ ]
281
+ }
282
+ }
283
+ ```
284
+
285
+ If a workflow is using a non-nullable field that's defined in the extension `schema` but is missing from the payload or there's a type mismatch between fields, then the action transiently fails.
286
+
287
+ The response size of the action must also be less than `50KB` exceeding this limit will also result in a transient failure. Actions that transiently fail will be retried at increasing intervals for up to 24 hours.
288
+
289
+ ## Sending complex objects in a trigger at runtime
290
+
291
+ When you execute the [`flowTriggerReceive`](/docs/apps/build/flow/triggers/create#step-4-test-your-trigger) mutation with one or more complex object fields, the payload must include a JSON representation of the complex object(s) matching the schema. For example, if the trigger has a field with key `Winning Bid` of type `Bid`, then the payload should include the following structure:
292
+
293
+ ```json
294
+ "payload": {
295
+ "Winning Bid": {
296
+ "id": "bid1",
297
+ "customerId": "gid://shopify/Customer/1",
298
+ "amount": 100.00
299
+ }
300
+ }
301
+ ```
data/scraped/raw/flow_migrate-legacy-extensions.txt ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ If you have existing Flow extensions that were created through the Partner Dashboard, then you can import these extensions into your codebase. After you deploy the extensions that you’ve imported into Shopify CLI, Shopify CLI manages those extensions going forward.
4
+
5
+ > Note:
6
+ > Extensions that are migrated to Shopify CLI use the `handle` properties. The `handle` property is a unique string that identifies your extension and that's used when interacting with the Shopify Flow API. For more information, refer to the [triggers](/docs/apps/build/flow/triggers/create#step-4-test-your-trigger) and [actions](/docs/apps/build/flow/actions/endpoints#request) runtime payloads.
7
+
8
+ A `handle` property is created in the extension's TOML configuration file after running the import command. Note that you can't change the `handle` property of the extensions that are present in your app's codebase after you've run the `dev` or `deploy` commands.
9
+
10
+ ### Requirements
11
+
12
+ - Create a [Partner account](https://www.shopify.com/partners).
13
+ - [Scaffold an app that uses Shopify CLI v3.70.0 or higher](/docs/apps/build/scaffold-app), or [migrate your existing app](/docs/apps/build/cli-for-apps/migrate-to-latest-cli) so it's compatible with Shopify CLI v3.70.0 or higher.
14
+ - [Migrate a Partner Dashboard-managed app](/docs/apps/build/cli-for-apps/migrate-from-dashboard).
15
+ <br>
16
+
17
+
18
+ ## Step 1: Import your Flow task extension locally
19
+
20
+ > Note:
21
+ > The command in this procedure only generates the local file representation of your Partner Dashboard extensions. Running the `deploy` command migrates your extensions to CLI managed-extensions. You can only import extensions that have versions. The published version is imported, if one exists. Otherwise, the latest version is imported.
22
+
23
+ 1. Navigate to your app directory.
24
+ 1. To start importing your Flow extension, run the following command:
25
+
26
+ ```bash
27
+ #!/bin/bash
28
+ shopify app import-extensions
29
+ ```
30
+
31
+ 1. Select the `Flow Extensions` option.
32
+ 1. Select an extension from the list of extensions that are available to import.
33
+
34
+ After you’ve selected the extension to import, Shopify CLI automatically generates the file representation in your application’s `/extensions` directory and displays a success message.
35
+
36
+ You can then go into your application’s `/extensions` directory and start editing your extension. The file structure of your extension should look like the following:
37
+
38
+ ```text
39
+ /my-flow-extension
40
+ shopify.extension.toml
41
+ ```
42
+
43
+ To learn more about the extensions file structure, refer to [App structure](/docs/apps/build/cli-for-apps/app-structure) and the documentation for your extension type.
44
+
45
+ ### Available Flags
46
+
47
+ #### `client_id`
48
+
49
+ An application’s `client_id`. The ID enables you to target a specific application when running the import command.
50
+
51
+ ```bash
52
+ #!/bin/bash
53
+ shopify app import-extensions --client_id abc123
54
+ ```
55
+
56
+ ## Step 2: Migrate your extension
57
+
58
+ After you've imported the extension, you can migrate your extension by using Shopify CLI's `deploy` command.
59
+
60
+ > Note:
61
+ > Deploying extensions using the `app deploy` command also publishes the extensions. We recommend testing changes by using [`app dev`](/docs/api/shopify-cli/app/app-dev) or deploying to a test app before deploying them to a production app.
62
+
63
+ Use Shopify CLI to deploy your extensions:
64
+
65
+ 1. Navigate to your app directory.
66
+ 2. Run the following command to start deploying your extension(s):
67
+
68
+ ```bash
69
+ #!/bin/bash
70
+ shopify app deploy
71
+ ```
72
+
73
+ 3. Follow the prompts.
74
+
75
+ When you receive confirmation that the deploy was successful, your extensions have been released.
76
+
data/scraped/raw/flow_templates.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## How templates work
4
+
5
+ A template in Shopify Flow is an example workflow that can be copied into a merchant's shop. Templates help merchants automate a specific use case with minimal or no additional configuration. Flow's template library offers hundreds of templates with features to filter, browse, and search. You can [create a template](/docs/apps/build/flow/templates/create-a-template) for Shopify Flow that showcases your custom triggers and actions and help merchants do more.
6
+
7
+
8
+ ![Flow template library](/assets/apps/flow/flow-template-library.png)
9
+
10
+ ## Next steps
11
+ - Follow our step by step guide on [creating a Flow template](/docs/apps/build/flow/templates/create-a-template).
12
+ - Learn more about how localize your template, the approval process, and more in the [reference resource](/docs/apps/build/flow/templates/reference#approval-process)
data/scraped/raw/flow_templates_create-a-template.txt ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ A template in Shopify Flow is an example workflow that can be copied into a merchant's shop. Templates help merchants automate a specific use case with minimal or no additional configuration. Flow's template library offers hundreds of templates with features to filter, browse, and search. You can create a template for Shopify Flow that showcases your custom triggers and actions and help merchants do more.
3
+
4
+
5
+ To create a workflow template that merchants can add to their workflow list, you need to add a Flow template extension to your app.
6
+
7
+ ## Requirements
8
+
9
+ - A [development store](/docs/api/development-stores) that has [Shopify Flow](https://apps.shopify.com/flow) and your app installed.
10
+ - Your existing custom triggers and actions are connected to your instance of Shopify Flow.
11
+ - [Shopify CLI](/docs/apps/build/cli-for-apps) installed with a version of `3.49` or higher.
12
+
13
+ ## Step 1: Create a workflow
14
+
15
+ A workflow is the foundation of a Flow template.
16
+
17
+ 1. In your development store navigate to **Apps** > **Flow**.
18
+ 2. Click **Create workflow**.
19
+ 3. In the workflow editor, build a workflow that solves a merchant use case and showcases your custom trigger and or actions.
20
+ 4. Optional: Tailor your template to a wider audience by [localizing your custom step descriptions](/docs/apps/build/flow/templates/reference#step-descriptions).
21
+ 5. After you're satisfied with your workflow, [export the workflow](https://help.shopify.com/en/manual/shopify-flow/manage#export-a-workflow) and save the `.flow` file locally.
22
+
23
+ > Note:
24
+ > - Remove any shop specific test data or replace with placeholder values if the merchant needs to provide a value. For example using the placeholder `YOUR_TAG_NAME` in a location where the merchant needs to provide a shop specific tag.<br />
25
+ > - Don't edit `.flow` files directly. Only make changes within the Flow app and export the updated workflow.<br />
26
+ > - Test your workflow thoroughly, ensuring the trigger, condition(s), and action(s) used provide the intended result.
27
+
28
+ ## Step 2: Create a Flow template extension
29
+
30
+ Use the Shopify CLI to generate a new extension:
31
+
32
+ 1. Navigate to your app directory.
33
+ 2. Run the following command:
34
+
35
+ <p>
36
+ <div class="react-code-block" data-preset="terminal">
37
+ <div class="react-code-block-preload ThemeMode-dim">
38
+ <div class="react-code-block-preload-bar "></div>
39
+ <div class="react-code-block-preload-placeholder-container">
40
+ <div class="react-code-block-preload-code-container">
41
+ <div class="react-code-block-preload-codeline-number"></div>
42
+ <div class="react-code-block-preload-codeline"></div>
43
+ </div>
44
+ <div class="react-code-block-preload-code-container">
45
+ <div class="react-code-block-preload-codeline-number"></div>
46
+ <div class="react-code-block-preload-codeline"></div>
47
+ </div>
48
+
49
+ </div>
50
+ </div>
51
+
52
+
53
+ <script type="text/plain" data-language="bash">
54
+ RAW_MD_CONTENT#!/bin/bash
55
+ shopify app generate extension
56
+ END_RAW_MD_CONTENT</script>
57
+
58
+ </div>
59
+ </p>
60
+
61
+
62
+ 3. Select the `Flow Template` as the type of extension.
63
+ 4. Provide a meaningful name for your extension.
64
+ <br>
65
+
66
+
67
+ The name that you provide displays in the Partners Dashboard. Follow these guidelines when choosing a name:
68
+
69
+ - Don't use punctuation.
70
+ - Separate words using spaces.
71
+
72
+ After you've followed the prompts, Shopify CLI generates the extension’s file representation in your app's `/extensions` directory and returns a success message. You can then go into your app's `/extensions` directory and start editing your new extension.
73
+
74
+ > Note:
75
+ > Each Flow template extension can contain only a single template. To deploy multiple templates, you will need to create an extension for each template.
76
+
77
+ The file structure of your extension should look like the following:
78
+
79
+ <p>
80
+ <div class="react-code-block" data-preset="file">
81
+ <div class="react-code-block-preload ThemeMode-dim">
82
+ <div class="react-code-block-preload-bar "></div>
83
+ <div class="react-code-block-preload-placeholder-container">
84
+ <div class="react-code-block-preload-code-container">
85
+ <div class="react-code-block-preload-codeline-number"></div>
86
+ <div class="react-code-block-preload-codeline"></div>
87
+ </div>
88
+ <div class="react-code-block-preload-code-container">
89
+ <div class="react-code-block-preload-codeline-number"></div>
90
+ <div class="react-code-block-preload-codeline"></div>
91
+ </div>
92
+ <div class="react-code-block-preload-code-container">
93
+ <div class="react-code-block-preload-codeline-number"></div>
94
+ <div class="react-code-block-preload-codeline"></div>
95
+ </div>
96
+ <div class="react-code-block-preload-code-container">
97
+ <div class="react-code-block-preload-codeline-number"></div>
98
+ <div class="react-code-block-preload-codeline"></div>
99
+ </div>
100
+ <div class="react-code-block-preload-code-container">
101
+ <div class="react-code-block-preload-codeline-number"></div>
102
+ <div class="react-code-block-preload-codeline"></div>
103
+ </div>
104
+ <div class="react-code-block-preload-code-container">
105
+ <div class="react-code-block-preload-codeline-number"></div>
106
+ <div class="react-code-block-preload-codeline"></div>
107
+ </div>
108
+
109
+ </div>
110
+ </div>
111
+
112
+ <script data-option="nocopy" data-value="true"></script>
113
+
114
+ <script type="text/plain" data-language="ssh">
115
+ RAW_MD_CONTENT/your-extension-name
116
+ /locales
117
+ en.default.json
118
+ fr.json
119
+ shopify.extension.toml
120
+ template.flow
121
+ END_RAW_MD_CONTENT</script>
122
+
123
+ </div>
124
+ </p>
125
+
126
+
127
+ To learn more about the extensions file structure, refer to our [app structure](/docs/apps/build/cli-for-apps/app-structure) documentation and the [documentation](/docs/apps/build/flow/templates/reference) for the Flow template extension type.
128
+
129
+ ## Step 3: Configure extension
130
+ Configure your template extension to include information describing it's function for merchants, and settings that control visibility.
131
+
132
+ 1. Update the [shopify.extension.toml configuration file](/docs/apps/build/flow/templates/reference#toml).
133
+ 2. Update and add any additional locales. [Localization reference](/docs/apps/build/flow/templates/reference#localization).
134
+ 3. Replace `template.flow` with the workflow [that you exported](/docs/apps/build/flow/templates/create-a-template#step-1-create-a-workflow).
135
+ 4. Be sure to update the filename to match your chosen file path in the `shopify.extension.toml` file. `template.flow` is the default.
136
+
137
+ ## Step 4: Preview extension
138
+
139
+ Preview your template extension to see how it will be displayed to merchants before deploying and requesting review.
140
+
141
+ 1. Run the following command in Shopify CLI:
142
+
143
+ <p>
144
+ <div class="react-code-block" data-preset="terminal">
145
+ <div class="react-code-block-preload ThemeMode-dim">
146
+ <div class="react-code-block-preload-bar "></div>
147
+ <div class="react-code-block-preload-placeholder-container">
148
+ <div class="react-code-block-preload-code-container">
149
+ <div class="react-code-block-preload-codeline-number"></div>
150
+ <div class="react-code-block-preload-codeline"></div>
151
+ </div>
152
+ <div class="react-code-block-preload-code-container">
153
+ <div class="react-code-block-preload-codeline-number"></div>
154
+ <div class="react-code-block-preload-codeline"></div>
155
+ </div>
156
+
157
+ </div>
158
+ </div>
159
+
160
+
161
+ <script type="text/plain" data-language="bash">
162
+ RAW_MD_CONTENT#!/bin/bash
163
+ shopify app dev
164
+ END_RAW_MD_CONTENT</script>
165
+
166
+ </div>
167
+ </p>
168
+
169
+
170
+ 2. In your development store's Shopify admin, navigate to [`/flow/editor/templates/dev`](https://admin.shopify.com/apps/flow/editor/templates/dev). From here you can preview your workflow, template card, and custom step descriptions.
171
+ 3. Refer to our [approval criteria](/docs/apps/build/flow/templates/reference#approval-process) to ensure that your extension meets our requirements.
172
+
173
+ ## Step 5: Deploy extension
174
+
175
+ Use Shopify CLI to deploy your extension.
176
+
177
+ 1. Navigate to your app directory.
178
+ 2. Run the following command to start deploying your extension(s):
179
+
180
+ <p>
181
+ <div class="react-code-block" data-preset="terminal">
182
+ <div class="react-code-block-preload ThemeMode-dim">
183
+ <div class="react-code-block-preload-bar "></div>
184
+ <div class="react-code-block-preload-placeholder-container">
185
+ <div class="react-code-block-preload-code-container">
186
+ <div class="react-code-block-preload-codeline-number"></div>
187
+ <div class="react-code-block-preload-codeline"></div>
188
+ </div>
189
+ <div class="react-code-block-preload-code-container">
190
+ <div class="react-code-block-preload-codeline-number"></div>
191
+ <div class="react-code-block-preload-codeline"></div>
192
+ </div>
193
+
194
+ </div>
195
+ </div>
196
+
197
+
198
+ <script type="text/plain" data-language="bash">
199
+ RAW_MD_CONTENT#!/bin/bash
200
+ shopify app deploy
201
+ END_RAW_MD_CONTENT</script>
202
+
203
+ </div>
204
+ </p>
205
+
206
+
207
+ 3. Follow the command prompts
208
+
209
+ When you receive confirmation that the deploy was successful, a new app version in your Partner Dashboard displays, where you can submit a request for review. After the request for review has been submitted and the [approval process](/docs/apps/build/flow/templates/reference#approval-process) is complete, you can release the new version from your Partner Dashboard and your templates will display in Flow's template library.
data/scraped/raw/flow_templates_reference.txt ADDED
@@ -0,0 +1,286 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ This guide provides explanations of key topics for building and deploying a Flow template extension. This includes the TOML configuration file, localization, and the template approval process.
4
+
5
+ ## TOML
6
+
7
+ When you first create a new Flow template extensions through Shopify CLI, you get a basic version of the `shopify.extension.toml` file structure that looks like the following example:
8
+
9
+ <p>
10
+ <div class="react-code-block" data-preset="file">
11
+ <div class="react-code-block-preload ThemeMode-dim">
12
+ <div class="react-code-block-preload-bar "></div>
13
+ <div class="react-code-block-preload-placeholder-container">
14
+ <div class="react-code-block-preload-code-container">
15
+ <div class="react-code-block-preload-codeline-number"></div>
16
+ <div class="react-code-block-preload-codeline"></div>
17
+ </div>
18
+ <div class="react-code-block-preload-code-container">
19
+ <div class="react-code-block-preload-codeline-number"></div>
20
+ <div class="react-code-block-preload-codeline"></div>
21
+ </div>
22
+ <div class="react-code-block-preload-code-container">
23
+ <div class="react-code-block-preload-codeline-number"></div>
24
+ <div class="react-code-block-preload-codeline"></div>
25
+ </div>
26
+ <div class="react-code-block-preload-code-container">
27
+ <div class="react-code-block-preload-codeline-number"></div>
28
+ <div class="react-code-block-preload-codeline"></div>
29
+ </div>
30
+ <div class="react-code-block-preload-code-container">
31
+ <div class="react-code-block-preload-codeline-number"></div>
32
+ <div class="react-code-block-preload-codeline"></div>
33
+ </div>
34
+ <div class="react-code-block-preload-code-container">
35
+ <div class="react-code-block-preload-codeline-number"></div>
36
+ <div class="react-code-block-preload-codeline"></div>
37
+ </div>
38
+ <div class="react-code-block-preload-code-container">
39
+ <div class="react-code-block-preload-codeline-number"></div>
40
+ <div class="react-code-block-preload-codeline"></div>
41
+ </div>
42
+ <div class="react-code-block-preload-code-container">
43
+ <div class="react-code-block-preload-codeline-number"></div>
44
+ <div class="react-code-block-preload-codeline"></div>
45
+ </div>
46
+ <div class="react-code-block-preload-code-container">
47
+ <div class="react-code-block-preload-codeline-number"></div>
48
+ <div class="react-code-block-preload-codeline"></div>
49
+ </div>
50
+ <div class="react-code-block-preload-code-container">
51
+ <div class="react-code-block-preload-codeline-number"></div>
52
+ <div class="react-code-block-preload-codeline"></div>
53
+ </div>
54
+ <div class="react-code-block-preload-code-container">
55
+ <div class="react-code-block-preload-codeline-number"></div>
56
+ <div class="react-code-block-preload-codeline"></div>
57
+ </div>
58
+ <div class="react-code-block-preload-code-container">
59
+ <div class="react-code-block-preload-codeline-number"></div>
60
+ <div class="react-code-block-preload-codeline"></div>
61
+ </div>
62
+ <div class="react-code-block-preload-code-container">
63
+ <div class="react-code-block-preload-codeline-number"></div>
64
+ <div class="react-code-block-preload-codeline"></div>
65
+ </div>
66
+ <div class="react-code-block-preload-code-container">
67
+ <div class="react-code-block-preload-codeline-number"></div>
68
+ <div class="react-code-block-preload-codeline"></div>
69
+ </div>
70
+ <div class="react-code-block-preload-code-container">
71
+ <div class="react-code-block-preload-codeline-number"></div>
72
+ <div class="react-code-block-preload-codeline"></div>
73
+ </div>
74
+ <div class="react-code-block-preload-code-container">
75
+ <div class="react-code-block-preload-codeline-number"></div>
76
+ <div class="react-code-block-preload-codeline"></div>
77
+ </div>
78
+ <div class="react-code-block-preload-code-container">
79
+ <div class="react-code-block-preload-codeline-number"></div>
80
+ <div class="react-code-block-preload-codeline"></div>
81
+ </div>
82
+
83
+ </div>
84
+ </div>
85
+
86
+ <script data-option="filename" data-value="shopify.extension.toml"></script>
87
+
88
+ <script type="text/plain" data-language="toml">
89
+ [[extensions]]
90
+ name = "t:name"
91
+ type = "flow_template"
92
+ handle = "example-name"
93
+ description = "t:description"
94
+
95
+ [extensions.template]
96
+
97
+ categories = ["orders", "risk"]
98
+
99
+ module = "./template.flow"
100
+
101
+ require_app = false
102
+
103
+ discoverable = true
104
+
105
+ enabled = true
106
+ </script>
107
+
108
+ </div>
109
+ </p>
110
+
111
+
112
+ ### Flow template extension fields
113
+
114
+ | Property | Description | Rules |
115
+ | ------------- | ---------------------------------------------------------------------------------- | ----------------- |
116
+ | `name` <br><span class="heading-flag">Required</span> | The title of the template. This property is translatable and will use the value for the key `name` in the translation files. | |
117
+ | `type` <br><span class="heading-flag">Required</span> | The type of your extension. This should always be set to `flow_template` for Flow templates.| - Value must be `flow_template`. |
118
+ | `handle` <br><span class="heading-flag">Required</span> | A globally-unique identifier for your extension. This property can't be changed after you’ve run the [`app dev`](/docs/api/shopify-cli/app/app-dev) or [`deploy`](/docs/api/shopify-cli/app/app-deploy) command. | - Can't exceed 30 characters.<br /> - Must only contain alphanumeric characters and hyphens. |
119
+ | `description` <br><span class="heading-flag">Optional</span> | The description of your template's workflow. This property is translatable and will use the value for the key `description` in the translation files. | |
120
+ | `categories` <br><span class="heading-flag">Required</span> | The categories that best describe the function of your template. | - Must be an array containing only strings of valid categories. <br /> - Must choose at least one category. Max 2 recommended. <br /> - Valid categories are: `buyer_experience`, `customers`, `inventory_and_merch`, `loyalty`, `orders`, `promotions`, `risk`, `fulfillment`, `b2b`, `payment_reminders`, `custom_data`, and `error_monitoring`. |
121
+ | `module` <br><span class="heading-flag">Required</span> | The file path of the template workflow in the extension's folder. |
122
+ | `require_app` <br><span class="heading-flag">Optional</span> | Whether your template is visible only to merchants who have your app installed. | - Defaults to `false`. |
123
+ | `discoverable` <br><span class="heading-flag">Optional</span> | Whether your template should be displayed in the template browser. When `false`, the template is accessible only through a deep link. | - Defaults to `true`. |
124
+ | `enabled` <br><span class="heading-flag">Optional</span> | Whether you template should be published and made available after being approved. | - Defaults to `true`.
125
+
126
+
127
+ ## Localization
128
+
129
+ Localizing your template by providing translated text allows a wider audience to understand your template better and can increase adoption.
130
+
131
+ You can provide translations for the following fields:
132
+
133
+ - **`name`**: Title of the template.
134
+ - **`description`**: Description of the template and it's purpose.
135
+ - **`preInstallNote`**: (Optional): Instructions for merchants to complete before activating the workflow. This field should only be included if setup is required before the template can be turned on.
136
+ - [Custom step descriptions](#step-descriptions) added within the workflow.
137
+
138
+ ### Adding additional locales
139
+
140
+ Add new `.json` files prefixed with the locale, for example `es.json`.
141
+
142
+ Add `default` to one of the locales to make it the fallback if a merchant's locale isn't in the locales you have provided. Example: `en.default.json`.
143
+
144
+ ### Step descriptions
145
+
146
+ You can provide translated custom step descriptions by adding a translation key wrapped by curly braces in the step description field. For example, `{expressShippingCondition}`. Ensure there's no other characters before or after `{yourKey}`. After adding this to your workflow, you can update the translation files to include the step description.
147
+
148
+ The following is an example:
149
+
150
+ ![How to format localized step descriptions in the Flow editor](/assets/apps/flow/localized_step_descriptions_in_flow_editor.png)
151
+
152
+ <p>
153
+ <div class="react-code-block" data-preset="file">
154
+ <div class="react-code-block-preload ThemeMode-dim">
155
+ <div class="react-code-block-preload-bar "></div>
156
+ <div class="react-code-block-preload-placeholder-container">
157
+ <div class="react-code-block-preload-code-container">
158
+ <div class="react-code-block-preload-codeline-number"></div>
159
+ <div class="react-code-block-preload-codeline"></div>
160
+ </div>
161
+ <div class="react-code-block-preload-code-container">
162
+ <div class="react-code-block-preload-codeline-number"></div>
163
+ <div class="react-code-block-preload-codeline"></div>
164
+ </div>
165
+ <div class="react-code-block-preload-code-container">
166
+ <div class="react-code-block-preload-codeline-number"></div>
167
+ <div class="react-code-block-preload-codeline"></div>
168
+ </div>
169
+ <div class="react-code-block-preload-code-container">
170
+ <div class="react-code-block-preload-codeline-number"></div>
171
+ <div class="react-code-block-preload-codeline"></div>
172
+ </div>
173
+ <div class="react-code-block-preload-code-container">
174
+ <div class="react-code-block-preload-codeline-number"></div>
175
+ <div class="react-code-block-preload-codeline"></div>
176
+ </div>
177
+ <div class="react-code-block-preload-code-container">
178
+ <div class="react-code-block-preload-codeline-number"></div>
179
+ <div class="react-code-block-preload-codeline"></div>
180
+ </div>
181
+
182
+ </div>
183
+ </div>
184
+
185
+ <script data-option="filename" data-value="en.default.json"></script>
186
+
187
+ <script type="text/plain" data-language="json">
188
+ {
189
+ "name": "My Awesome Template!",
190
+ "description": "A template that helps increase merchant productivity",
191
+ "preInstallNote": "You must disable automatic payment capture in the Shopify Admin before using this template",
192
+ "expressShippingCondition": "This step will check if the order uses express shipping"
193
+ }
194
+ </script>
195
+
196
+ </div>
197
+ </p>
198
+
199
+
200
+ ## Approval process
201
+
202
+ Before submitting your template extension for approval ensure that it meets the following criteria:
203
+
204
+ ### Workflow
205
+
206
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-1">
207
+ <label class="marketing-checkbox-label" for="template-criteria-1">
208
+ <p style="margin-left:30px">Provides value/solves a problem. For example, notifying the merchant when a buyer makes 10 purchases and adds a `VIP` tag to the customer.</p>
209
+ </label>
210
+
211
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-2">
212
+ <label class="marketing-checkbox-label" for="template-criteria-2">
213
+ <p style="margin-left:30px">Does not already exist within the [template library](https://admin.shopify.com/apps/flow/web/editor/templates).</p>
214
+ </label>
215
+
216
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-3">
217
+ <label class="marketing-checkbox-label" for="template-criteria-3">
218
+ <p style="margin-left:30px">Isn't malicious in its execution.</p>
219
+ </label>
220
+
221
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-4">
222
+ <label class="marketing-checkbox-label" for="template-criteria-4">
223
+ <p style="margin-left:30px">Is complete in its configuration. Validation errors might exist in the workflow where fields are left blank for input unique to the merchant.</p>
224
+ </label>
225
+
226
+ ### TOML
227
+
228
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-5">
229
+ <label class="marketing-checkbox-label" for="template-criteria-5">
230
+ <p style="margin-left:30px">Titles should use the format, "\<Description of key action\> when \<description of trigger\>".</p>
231
+ </label>
232
+
233
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-6">
234
+ <label class="marketing-checkbox-label" for="template-criteria-6">
235
+ <p style="margin-left:30px">Includes all required fields.</p>
236
+ </label>
237
+
238
+ ### Localization
239
+
240
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-7">
241
+ <label class="marketing-checkbox-label" for="template-criteria-7">
242
+ <p style="margin-left:30px">Has correct spelling and grammar.</p>
243
+ </label>
244
+
245
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-8">
246
+ <label class="marketing-checkbox-label" for="template-criteria-8">
247
+ <p style="margin-left:30px">Has a default localization, for example <code>en.default.json</code>.</p>
248
+ </label>
249
+
250
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-9">
251
+ <label class="marketing-checkbox-label" for="template-criteria-9">
252
+ <p style="margin-left:30px">Has an English translation.</p>
253
+ </label>
254
+
255
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-10">
256
+ <label class="marketing-checkbox-label" for="template-criteria-10">
257
+ <p style="margin-left:30px">Include the <code>preInstallNote</code> field if setup is required before the template can be turned on. If no prior setup is needed, then remove the <code>preInstallNote</code> field from the localization files before submitting the template extension.</p>
258
+ </label>
259
+
260
+ ### Access
261
+
262
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-11">
263
+ <label class="marketing-checkbox-label" for="template-criteria-11">
264
+ <p style="margin-left:30px">Flow’s testing account, at flow-connector-testing.myshopify.com has access to any actions, triggers, or resources that are required to test the templates, including access to the app.</p>
265
+ </label>
266
+
267
+ ### Limitations
268
+
269
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-12">
270
+ <label class="marketing-checkbox-label" for="template-criteria-12">
271
+ <p style="margin-left:30px">A maximum of 25 templates can be submitted for each app.</p>
272
+ </label>
273
+
274
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-13">
275
+ <label class="marketing-checkbox-label" for="template-criteria-13">
276
+ <p style="margin-left:30px">Public apps must be listed in the [Shopify App Store](https://apps.shopify.com/) prior to submitting a template.</p>
277
+ </label>
278
+
279
+ <input class="marketing-checkbox" type="checkbox" id="template-criteria-14">
280
+ <label class="marketing-checkbox-label" for="template-criteria-14">
281
+ <p style="margin-left:30px">Don't edit the `.flow` file directly. Only change and export updated workflows using the Flow app.</p>
282
+ </label>
283
+
284
+ ### Submitting your extension for approval
285
+
286
+ After you're satisfied with your template extension, [`deploy`](/docs/api/shopify-cli/app/app-deploy) a new app version from Shopify CLI. The Flow team will review your templates within three business days. Template reviews don't block your app version from releasing, but template changes won't be reflected until the approval process is complete. If we require changes, then we'll reject the review and follow up through email with feedback.
data/scraped/raw/flow_track-lifecycle-events.txt ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ This guide explains how to configure your app to receive trigger lifecycle callbacks from Shopify Flow.
4
+
5
+ When [creating a trigger](/docs/apps/build/flow/triggers/create), configuring a lifecycle callback enables your app to receive notifications from Shopify Flow about stores using the trigger and communicate changes in workflow status (e.g., enabling or disabling a workflow) back to the app. This helps optimize app performance by ensuring that trigger-related operations are only performed for stores that actually need them.
6
+
7
+ Apps must be properly configured to respond to trigger lifecycle callbacks. When a merchant attempts to enable a workflow that uses the trigger, Shopify Flow sends a lifecycle callback to the app's web server. If it doesn't promptly receive a response or receives a response with an HTTP status code that isn't `2xx`, then the merchant can't enable the workflow and make use of the trigger.
8
+
9
+ > Note:
10
+ > Legacy trigger discovery webhook extensions created using the Partner Dashboard are deprecated and must [migrate to the CLI](docs/apps/build/flow/migrate-legacy-extensions) before they can be edited.
11
+
12
+ ## How trigger lifecycle callbacks work
13
+
14
+ Trigger lifecycle callbacks contain identifying information about the trigger and the store using it and indicate whether the trigger is being used. You can use this information to track the stores that are currently using your triggers and then send trigger requests to only those stores.
15
+
16
+ ### Properties
17
+
18
+ The trigger lifecycle callback (HTTP POST request) is formatted in JSON and it contains the following properties:
19
+
20
+ <table>
21
+ <tr>
22
+ <th>Property</th>
23
+ <th>Data type</th>
24
+ <th width="40%">Description</th>
25
+ <th>Example</th>
26
+ </tr>
27
+ <tr>
28
+ <td><code>flow_trigger_definition_id</code></td>
29
+ <td>String</td>
30
+ <td>The unique identifier for your Shopify Flow trigger.</td>
31
+ <td>Add row to spreadsheet</td>
32
+ </tr>
33
+ <tr>
34
+ <td><code>has_enabled_flow</code></td>
35
+ <td>Boolean</td>
36
+ <td>Whether the store has an enabled workflow that uses your trigger. Valid values:
37
+ <ul>
38
+ <li><code>true</code>: There is at least one workflow that is enabled and that uses your trigger.</li>
39
+ <li><code>false</code>: There are no enabled workflows that use your trigger.</li>
40
+ </ul>
41
+ </td>
42
+ <td>true</td>
43
+ </tr>
44
+ <tr>
45
+ <td><code>shop_id</code></td>
46
+ <td>Number</td>
47
+ <td>The unique identifier for the Shopify store.</td>
48
+ <td>690933842</td>
49
+ </tr>
50
+ <tr>
51
+ <td><code>shopify_domain</code></td>
52
+ <td>String</td>
53
+ <td>The myshopify domain of the Shopify store.</td>
54
+ <td>johnsapparel.myshopify.com</td>
55
+ </tr>
56
+ <tr>
57
+ <td><code>timestamp</code></td>
58
+ <td><a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a> date and timestamp</td>
59
+ <td>
60
+ <p>The time when the notification was created. Notifications with newer timestamps should take precedence. If you already have a timestamp in your datastore and you receive a newer timestamp, then overwrite this payload's information in your datastore. Conversely, if you receive a timestamp that is older than the information in your datastore, then ignore this payload.</p>
61
+ </td>
62
+ <td>2019-01-25T16:44:10.999Z</td>
63
+ </tr>
64
+ </table>
65
+
66
+ The following is an example body of a usage notification (HTTP POST) request:
67
+
68
+ ```json
69
+ {
70
+ "flow_trigger_definition_id": "Add row to spreadsheet",
71
+ "has_enabled_flow": false,
72
+ "shop_id": "690933842",
73
+ "shopify_domain": "johnapparel.myshopify.com",
74
+ "timestamp": "2019-01-25T16:44:10.999Z"
75
+ }
76
+ ```
77
+
78
+ ### Callback events
79
+
80
+ Shopify Flow sends trigger lifecycle callbacks when the following events occur:
81
+
82
+ - When a merchant activates a workflow that uses your trigger, the callback contains `"has_enabled_flow": true`.
83
+ - When a merchant deactivates a workflow that uses your trigger, the callback contains `"has_enabled_flow": false`.
84
+
85
+ ### Web server response time and status codes
86
+
87
+ When a merchant tries to enable a workflow that uses your trigger, Shopify Flow sends a trigger lifecycle callback to your web server. If your web server doesn't respond within five seconds, or if it responds with a different status code, then the merchant can't enable that workflow. The merchant receives a notification in the Shopify Flow app that tells them to try enabling the workflow at a later time.
88
+
89
+ ## 1. Configure your web server
90
+
91
+ To begin, configure your web server to listen for Shopify Flow callbacks.
92
+
93
+ 1. Configure a URL in your web server to listen for the trigger lifecycle callbacks from Shopify Flow.
94
+ 2. Configure your web server to verify the HMAC header in the trigger lifecycle callback with your client secret.
95
+
96
+ The HMAC header is located in the following HTTP header: `x-shopify-hmac-sha256`. If you are using a Ruby-based web framework, then the header is `http-x-shopify-hmac-sha256`.
97
+
98
+ 3. Configure your web server to respond within 5 seconds when it receives a trigger lifecycle callback.
99
+
100
+ ## 2. Process and store callback data
101
+
102
+ After you've added support to listen for Shopify Flow callbacks, you can configure your web server to process and store the callback data.
103
+
104
+ 1. Save the list of stores that are using your triggers in a persistent datastore. Use the <code>timestamp</code> property to make sure that you don't overwrite an existing entry with older information.
105
+ 2. Edit your application to send your triggers only to stores that are using your triggers.
106
+
107
+ ## 3. Configure the callback
108
+
109
+ Finally, configure the callback in the CLI:
110
+
111
+ 1. Run `shopify app generate extension`.
112
+ 2. Select `Flow trigger lifecycle callback`.
113
+ 3. Change the URL in the generated TOML to the URL configured on the web server.
114
+ 4. Run `shopify app deploy`.
115
+
116
+ ## Next steps
117
+
118
+ - Familiarize yourself with [Shopify Flow](/docs/apps/build/flow) and learn about building connectors.
119
+ - Connect your app to Shopify Flow so that events that occur in your app can [trigger workflows](/docs/apps/build/flow/triggers).
120
+ - Connect your app to Shopify Flow so that your app receives data and information when a [workflow action](/docs/apps/build/flow/actions) runs.
data/scraped/raw/flow_triggers.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## How triggers work
4
+
5
+ A trigger is a task in Shopify Flow that starts the execution of a workflow. The trigger represents an event that happens in a store or in an app. You can [build a trigger](/docs/apps/build/flow/triggers/create) for Shopify Flow so that events in your app trigger workflows to run.
6
+
7
+ ![A diagram that show how third party triggers interface with Flow ](/assets/apps/flow/trigger_diagram.png)
8
+
9
+ ## Next steps
10
+
11
+ - To build a trigger, you need to [create a trigger extension](/docs/apps/build/flow/triggers/create) in your app. In that extension, you specify details about the trigger using a [TOML file](/docs/apps/build/flow/triggers/reference).
12
+ - Once you have published your extension, you can then test or use it by [calling the Shopify API](/docs/apps/build/flow/triggers/reference#mutation-api-reference) with the trigger payload.
data/scraped/raw/flow_triggers_create.txt ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## Requirements
4
+
5
+ Make sure that you have the following:
6
+
7
+ - A test web server that you can use to send information to Shopify Flow. You can use an existing web server. This web server needs to be able to send POST requests to Shopify's [GraphQL Admin API](/docs/api/admin-graphql).
8
+ - A test app that works with the test web server and can send HTTP requests.
9
+ - A development store that has [Shopify Flow](https://apps.shopify.com/flow) and the test app installed.
10
+ - Your application has access to the `read_customers` scope. The trigger you will build using this tutorial will be using a customer reference which requires that scope.
11
+
12
+ ## Step 1: Create a Flow trigger extension
13
+
14
+ To give your Flow action a meaningful name, use the following guidelines:
15
+
16
+ - Use an object acted on + past tense verb format. For example, `Auction bid placed`.
17
+ - Use sentence case.
18
+ - Don't use punctuation.
19
+ - Separate words using spaces.
20
+
21
+ ### Using Shopify CLI
22
+
23
+ The following steps show how to create a trigger that sends bid information to Shopify Flow when a bid is placed on an auction.
24
+
25
+ Use the Shopify CLI to generate a new extension:
26
+
27
+ 1. Navigate to your app directory.
28
+ 2. Run the following command:
29
+
30
+ <p>
31
+ <div class="react-code-block" data-preset="terminal">
32
+ <div class="react-code-block-preload ThemeMode-dim">
33
+ <div class="react-code-block-preload-bar "></div>
34
+ <div class="react-code-block-preload-placeholder-container">
35
+ <div class="react-code-block-preload-code-container">
36
+ <div class="react-code-block-preload-codeline-number"></div>
37
+ <div class="react-code-block-preload-codeline"></div>
38
+ </div>
39
+ <div class="react-code-block-preload-code-container">
40
+ <div class="react-code-block-preload-codeline-number"></div>
41
+ <div class="react-code-block-preload-codeline"></div>
42
+ </div>
43
+
44
+ </div>
45
+ </div>
46
+
47
+
48
+ <script type="text/plain" data-language="bash">
49
+ RAW_MD_CONTENT#!/bin/bash
50
+ shopify app generate extension
51
+ END_RAW_MD_CONTENT</script>
52
+
53
+ </div>
54
+ </p>
55
+
56
+
57
+ 3. Select the `Flow Trigger` as the type of extension.
58
+ 4. Provide a meaningful name for your extension.
59
+ <br>
60
+
61
+
62
+ After you've followed the prompts, Shopify CLI generates the extension’s file representation in your app's `/extensions` directory and gives you a success message. You can then go into your app's `/extensions` directory and start editing your new extension.
63
+
64
+ The file structure of your extension should look like the following:
65
+
66
+ ```
67
+ /auction-bid-placed
68
+ shopify.extension.toml
69
+ ```
70
+
71
+ To learn more about the extensions file structure, refer to [App structure](/docs/apps/build/cli-for-apps/app-structure) and the documentation for your extension type.
72
+
73
+ ### Using the Partner Dashboard
74
+
75
+ 1. Open your [Partner Dashboard](https://partners.shopify.com).
76
+ 2. Click the app that you want to add your Shopify Flow trigger to.
77
+ 3. Click **Extensions**, then click **Create** or **Create extension**.
78
+ 4. Under **Flow**, click the **Flow/Triggers** card.
79
+ 5. Enter an internal extension name for your trigger and click **Save**.
80
+ 6. Enter a title and description for the trigger that will be shown to merchants.
81
+ 7. Copy the GraphQL endpoint that displays under the **Trigger description** field to a text file. Your app uses this endpoint to send your POST request to Shopify Flow. The endpoint follows the format `https://{shop}.myshopify.com/admin/api/latest/graphql.json`.
82
+ 8. In the **Request body properties** section, click **Add property**, choose a data type, and create the properties that display in Shopify Flow when a merchant chooses your trigger.
83
+
84
+ ## Step 2: Customize a Flow trigger configuration file
85
+
86
+ The following procedure requires you to have generated a flow extension using Shopify CLI. In this section you'll use the default trigger template and update it to be a functional extension example.
87
+
88
+ 1. Change description to `Trigger for auction bids.`
89
+ 2. On the second `[[settings.fields]]` field, update:
90
+ - `type` to `number_decimal`
91
+ - `key` to `Amount`
92
+
93
+ <p>
94
+ <div class="react-code-block" data-preset="file">
95
+ <div class="react-code-block-preload ThemeMode-dim">
96
+ <div class="react-code-block-preload-bar "></div>
97
+ <div class="react-code-block-preload-placeholder-container">
98
+ <div class="react-code-block-preload-code-container">
99
+ <div class="react-code-block-preload-codeline-number"></div>
100
+ <div class="react-code-block-preload-codeline"></div>
101
+ </div>
102
+ <div class="react-code-block-preload-code-container">
103
+ <div class="react-code-block-preload-codeline-number"></div>
104
+ <div class="react-code-block-preload-codeline"></div>
105
+ </div>
106
+ <div class="react-code-block-preload-code-container">
107
+ <div class="react-code-block-preload-codeline-number"></div>
108
+ <div class="react-code-block-preload-codeline"></div>
109
+ </div>
110
+ <div class="react-code-block-preload-code-container">
111
+ <div class="react-code-block-preload-codeline-number"></div>
112
+ <div class="react-code-block-preload-codeline"></div>
113
+ </div>
114
+ <div class="react-code-block-preload-code-container">
115
+ <div class="react-code-block-preload-codeline-number"></div>
116
+ <div class="react-code-block-preload-codeline"></div>
117
+ </div>
118
+ <div class="react-code-block-preload-code-container">
119
+ <div class="react-code-block-preload-codeline-number"></div>
120
+ <div class="react-code-block-preload-codeline"></div>
121
+ </div>
122
+ <div class="react-code-block-preload-code-container">
123
+ <div class="react-code-block-preload-codeline-number"></div>
124
+ <div class="react-code-block-preload-codeline"></div>
125
+ </div>
126
+ <div class="react-code-block-preload-code-container">
127
+ <div class="react-code-block-preload-codeline-number"></div>
128
+ <div class="react-code-block-preload-codeline"></div>
129
+ </div>
130
+ <div class="react-code-block-preload-code-container">
131
+ <div class="react-code-block-preload-codeline-number"></div>
132
+ <div class="react-code-block-preload-codeline"></div>
133
+ </div>
134
+ <div class="react-code-block-preload-code-container">
135
+ <div class="react-code-block-preload-codeline-number"></div>
136
+ <div class="react-code-block-preload-codeline"></div>
137
+ </div>
138
+ <div class="react-code-block-preload-code-container">
139
+ <div class="react-code-block-preload-codeline-number"></div>
140
+ <div class="react-code-block-preload-codeline"></div>
141
+ </div>
142
+ <div class="react-code-block-preload-code-container">
143
+ <div class="react-code-block-preload-codeline-number"></div>
144
+ <div class="react-code-block-preload-codeline"></div>
145
+ </div>
146
+ <div class="react-code-block-preload-code-container">
147
+ <div class="react-code-block-preload-codeline-number"></div>
148
+ <div class="react-code-block-preload-codeline"></div>
149
+ </div>
150
+ <div class="react-code-block-preload-code-container">
151
+ <div class="react-code-block-preload-codeline-number"></div>
152
+ <div class="react-code-block-preload-codeline"></div>
153
+ </div>
154
+
155
+ </div>
156
+ </div>
157
+
158
+
159
+ <script type="text/plain" data-language="bash" data-title="toml">
160
+ RAW_MD_CONTENT[[extensions]]
161
+ name = "Auction Bid Placed"
162
+ type = "flow_trigger"
163
+ handle = "auction-bid-placed"
164
+ description = "Trigger for auction bids."
165
+
166
+ [settings]
167
+
168
+ [[settings.fields]]
169
+ type = "customer_reference"
170
+
171
+ [[settings.fields]]
172
+ type = "number_decimal"
173
+ key = "Amount"
174
+ END_RAW_MD_CONTENT</script>
175
+
176
+ </div>
177
+ </p>
178
+
179
+
180
+ ## Step 3: Enable the draft version of your trigger
181
+
182
+ Running [`app dev`](/docs/api/shopify-cli/app/app-dev) allows changes made to local files to update the draft version of your Flow task extensions. The draft version is only available in your development store.
183
+
184
+ > Note:
185
+ > When [`app dev`](/docs/api/shopify-cli/app/app-dev) is running and "Development store preview" is enabled, the draft version of a task will appear in your development store _in place_ of the deployed version. Other shops will continue to see the deployed version of your task (if one exists). Draft versions can be identified by the "draft" badge. To see the deployed version of the task in your development store, turn off "Development store preview" in the "Extensions" section of your app in [Shopify Partners](https://partners.shopify.com/).
186
+
187
+ 1. Navigate to your app directory.
188
+ 2. Run the following command to start using draft versions of your extension(s):
189
+
190
+ ```bash
191
+ #!/bin/bash
192
+ shopify app dev
193
+ ```
194
+
195
+ 3. Follow the prompts.
196
+
197
+
198
+ ## Step 4: Test your trigger
199
+
200
+ After the [`app dev`](/docs/api/shopify-cli/app/app-dev) command has started, you can test the draft version of your trigger in Shopify Flow.
201
+
202
+ 1. In your development store, create a [workflow](https://www.shopify.com/admin/apps/flow) that uses the trigger that you created for your app.
203
+
204
+ 2. Using the Admin GraphQL API, send a `flowTriggerReceive` mutation with the following arguments:
205
+
206
+ - The `handle` of the trigger
207
+ - The `payload` of the trigger containing the fields defined in the extension TOML
208
+ - The size of the payload (keys included) must be under 50 KB. If the size of the properties body exceeds the limit, then Shopify responds to the GraphQL request with a validation error reading `Properties size exceeds the limit of 50000 bytes`. As a result, workflows with the specified trigger won't start from this request.
209
+
210
+ The following is an example of a `flowTriggerReceive` mutation:
211
+
212
+ ```graphql
213
+ mutation
214
+ {
215
+ flowTriggerReceive(
216
+ handle: "auction-bid-placed",
217
+ payload: {
218
+ "Amount": "30",
219
+ "customer_id": 12345
220
+ })
221
+ {
222
+ userErrors {field, message}
223
+ }
224
+ }
225
+ ```
226
+
227
+ > [Learn how to authenticate your GraphQL Admin API requests](/docs/api/admin-graphql#authentication).
228
+
229
+ The following example shows the same mutation sent in a curl request:
230
+
231
+ ```curl
232
+ curl --location 'https://{shop_domain}.myshopify.com/admin/api/latest/graphql.json' \
233
+ --header 'X-Shopify-Access-Token: {access_token}' \
234
+ --header 'Content-Type: application/json' \
235
+ --data '{
236
+ "query": "mutation flowTriggerReceive($handle: String, $payload: JSON) { flowTriggerReceive(handle: $handle, payload: $payload) { userErrors { message field } } }",
237
+ "variables": {
238
+ "handle": "auction-bid-placed",
239
+ "payload": {
240
+ "customer_id": {customer_id},
241
+ "Amount": 30
242
+ }
243
+ }
244
+ }'
245
+ ```
246
+
247
+ ## Step 5: Deploy your extension
248
+
249
+ > Note:
250
+ > Deploying extensions using the `app deploy` command also publishes the extensions. We recommend testing changes by using [`app dev`](/docs/api/shopify-cli/app/app-dev) or deploying to a test app before deploying them to a production app.
251
+
252
+ Use Shopify CLI to deploy your extensions:
253
+
254
+ 1. Navigate to your app directory.
255
+ 2. Run the following command to start deploying your extension(s):
256
+
257
+ ```bash
258
+ #!/bin/bash
259
+ shopify app deploy
260
+ ```
261
+
262
+ 3. Follow the prompts.
263
+
264
+ When you receive confirmation that the deploy was successful, your extensions have been released.
265
+
266
+
267
+ ## Next steps
268
+
269
+ - Familiarize yourself with [Shopify Flow](/docs/apps/build/flow) and learn about building connectors.
270
+ - Connect your app to Shopify Flow so that your app receives data and information when a [workflow action](/docs/apps/build/flow/actions) runs.
271
+ - Learn how to receive [lifecycle events from Shopify Flow](/docs/apps/build/flow/track-lifecycle-events) about the stores that are using your triggers in enabled workflows.
272
+ - Learn how to use [complex data types](/docs/apps/build/flow/configure-complex-data-types) in your Shopify Flow trigger.
data/scraped/raw/flow_triggers_reference.txt ADDED
@@ -0,0 +1,310 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ When you create a new trigger extension using Shopify CLI, a basic version of the TOML configuration file structure is generated. In this guide, you'll learn about configuring the different sections and properties of the configuration file, including extension properties, extension fields, reference field types, custom field types, and more.
4
+
5
+ This guide will also inform you how to make HTTP requests to Flow to start the workflows in which your extension is the trigger.
6
+
7
+ ## TOML
8
+
9
+ > Note:
10
+ > Creating Flow extensions using Shopify CLI is an exciting new feature that is currently in development. As with any developing feature, it's important to note that the Flow's CLI capabilities will continue to evolve and improve over time. Developers can expect additional functionality, enhancements, and improvements to be added as development progresses.
11
+ >
12
+ >To create Flow extensions using [Shopify CLI](https://www.npmjs.com/package/@shopify/cli), ensure you have the latest version installed.
13
+
14
+
15
+ When you create a new trigger extension using Shopify CLI, you'll get a basic version of the TOML configuration file structure which should look like the following example:
16
+
17
+ <p>
18
+ <div class="react-code-block" data-preset="file">
19
+ <div class="react-code-block-preload ThemeMode-dim">
20
+ <div class="react-code-block-preload-bar "></div>
21
+ <div class="react-code-block-preload-placeholder-container">
22
+ <div class="react-code-block-preload-code-container">
23
+ <div class="react-code-block-preload-codeline-number"></div>
24
+ <div class="react-code-block-preload-codeline"></div>
25
+ </div>
26
+ <div class="react-code-block-preload-code-container">
27
+ <div class="react-code-block-preload-codeline-number"></div>
28
+ <div class="react-code-block-preload-codeline"></div>
29
+ </div>
30
+ <div class="react-code-block-preload-code-container">
31
+ <div class="react-code-block-preload-codeline-number"></div>
32
+ <div class="react-code-block-preload-codeline"></div>
33
+ </div>
34
+ <div class="react-code-block-preload-code-container">
35
+ <div class="react-code-block-preload-codeline-number"></div>
36
+ <div class="react-code-block-preload-codeline"></div>
37
+ </div>
38
+ <div class="react-code-block-preload-code-container">
39
+ <div class="react-code-block-preload-codeline-number"></div>
40
+ <div class="react-code-block-preload-codeline"></div>
41
+ </div>
42
+ <div class="react-code-block-preload-code-container">
43
+ <div class="react-code-block-preload-codeline-number"></div>
44
+ <div class="react-code-block-preload-codeline"></div>
45
+ </div>
46
+ <div class="react-code-block-preload-code-container">
47
+ <div class="react-code-block-preload-codeline-number"></div>
48
+ <div class="react-code-block-preload-codeline"></div>
49
+ </div>
50
+ <div class="react-code-block-preload-code-container">
51
+ <div class="react-code-block-preload-codeline-number"></div>
52
+ <div class="react-code-block-preload-codeline"></div>
53
+ </div>
54
+ <div class="react-code-block-preload-code-container">
55
+ <div class="react-code-block-preload-codeline-number"></div>
56
+ <div class="react-code-block-preload-codeline"></div>
57
+ </div>
58
+ <div class="react-code-block-preload-code-container">
59
+ <div class="react-code-block-preload-codeline-number"></div>
60
+ <div class="react-code-block-preload-codeline"></div>
61
+ </div>
62
+ <div class="react-code-block-preload-code-container">
63
+ <div class="react-code-block-preload-codeline-number"></div>
64
+ <div class="react-code-block-preload-codeline"></div>
65
+ </div>
66
+ <div class="react-code-block-preload-code-container">
67
+ <div class="react-code-block-preload-codeline-number"></div>
68
+ <div class="react-code-block-preload-codeline"></div>
69
+ </div>
70
+ <div class="react-code-block-preload-code-container">
71
+ <div class="react-code-block-preload-codeline-number"></div>
72
+ <div class="react-code-block-preload-codeline"></div>
73
+ </div>
74
+ <div class="react-code-block-preload-code-container">
75
+ <div class="react-code-block-preload-codeline-number"></div>
76
+ <div class="react-code-block-preload-codeline"></div>
77
+ </div>
78
+
79
+ </div>
80
+ </div>
81
+
82
+
83
+ <script type="text/plain" data-language="bash" data-title="toml">
84
+ [[extensions]]
85
+ name = "Auction Bid"
86
+ type = "flow_trigger"
87
+ handle = "auction-bid"
88
+ description = "Your description"
89
+
90
+ [settings]
91
+
92
+ [[settings.fields]]
93
+ type = "customer_reference"
94
+
95
+ [[settings.fields]]
96
+ type = "single_line_text_field"
97
+ key = "your field key"
98
+ </script>
99
+
100
+ </div>
101
+ </p>
102
+
103
+
104
+ ### Trigger extension properties
105
+
106
+ Extension properties are listed in the `[[extensions]]` section and enable you to define the interface between Flow and your event.
107
+
108
+ | Property name | Description | Rules |
109
+ | --------------------------- | ------------------------------------------------------------- | -------------------------------------- |
110
+ | `name` <br><span class="heading-flag">Required</span> | Name of your extension. Will be the merchant-facing name of your task in the editor. This should be something that is human readable. | |
111
+ | `type` <br><span class="heading-flag">Required</span> | The type of your extension. This should always be set to “flow_trigger” for Flow triggers. | - Value must be `flow_trigger`.
112
+ | `handle` <br><span class="heading-flag">Required</span> | A unique identifier for your extension. This property cannot be changed once you’ve run the `dev` or `deploy` command. | - Cannot exceed 30 characters.<br /> - Must be unique across your app's extensions. <br /> - Must only contain alphanumeric characters and hyphens. |
113
+ | `description` <br><span class="heading-flag">Optional</span> | A description of your extension. This description will be shown in the Flow editor navigation panel. | |
114
+
115
+ ### Trigger extension fields
116
+
117
+ Trigger extension fields are listed in the `[settings]` section, with each field using a `[[settings.field]]` header. These fields define the payload your event will send to Flow. You can add more than one field to your Flow trigger. The order of the fields in the TOML file is preserved when they're being rendered in the editor configuration panel. When sending a trigger payload, all fields defined in a trigger are required.
118
+
119
+ | Property name | Description | Rules |
120
+ | ------------------------------ | --------------------------------------------------------------------------------------------------- | --------------------------------|
121
+ | `type` <br><span class="heading-flag">Required</span> | The field type. | - [Accepted custom field types](#custom-field-types).<br> - [Accepted reference field types](#reference-field-types). |
122
+ | `key` <br><span class="heading-flag">Optional</span> | A unique key that identifies your field. This should be human readable since it will appear in the Flow editor in the environment picker menu. | - Required for custom field types. <br /> Should only contain alphabetic values or spaces. <br /> - This property is not valid for reference field types. |
123
+ | `description` <br><span class="heading-flag">Required</span> | A description of the field. This will appear in the Flow editor configuration panel. |
124
+
125
+ ### Supported field types
126
+
127
+ When you create a trigger, you add the fields that your trigger sends to Shopify Flow in the `[settings]` section of the TOML file. These fields define what your event plans to send to Shopify Flow. Merchants can then use that data in their conditions and actions.
128
+
129
+ You can add two types of fields: custom fields or predefined reference fields.
130
+
131
+ ![A diagram that shows how trigger properties are rendered in the Flow editor](/assets/apps/flow/trigger_properties_in_flow_editor.png)
132
+
133
+ ### Reference field types
134
+
135
+ A reference field lets you send the identifier of a Shopify resource to Shopify Flow. This allows merchants to build workflows that use any data related to that resource.
136
+
137
+ For example, your trigger sends a customer ID to Shopify Flow. The merchant can create a condition that checks `customer / amountSpent` and `customer / tags`. In their action, the merchant can include the template variables for customers, such as `{{customer.email}}`.
138
+
139
+ To specify that a trigger will include a reference field, you only need to specify the `type` and an optional `description` property. For example:
140
+
141
+ <p>
142
+ <div class="react-code-block" data-preset="file">
143
+ <div class="react-code-block-preload ThemeMode-dim">
144
+ <div class="react-code-block-preload-bar "></div>
145
+ <div class="react-code-block-preload-placeholder-container">
146
+ <div class="react-code-block-preload-code-container">
147
+ <div class="react-code-block-preload-codeline-number"></div>
148
+ <div class="react-code-block-preload-codeline"></div>
149
+ </div>
150
+ <div class="react-code-block-preload-code-container">
151
+ <div class="react-code-block-preload-codeline-number"></div>
152
+ <div class="react-code-block-preload-codeline"></div>
153
+ </div>
154
+ <div class="react-code-block-preload-code-container">
155
+ <div class="react-code-block-preload-codeline-number"></div>
156
+ <div class="react-code-block-preload-codeline"></div>
157
+ </div>
158
+ <div class="react-code-block-preload-code-container">
159
+ <div class="react-code-block-preload-codeline-number"></div>
160
+ <div class="react-code-block-preload-codeline"></div>
161
+ </div>
162
+ <div class="react-code-block-preload-code-container">
163
+ <div class="react-code-block-preload-codeline-number"></div>
164
+ <div class="react-code-block-preload-codeline"></div>
165
+ </div>
166
+ <div class="react-code-block-preload-code-container">
167
+ <div class="react-code-block-preload-codeline-number"></div>
168
+ <div class="react-code-block-preload-codeline"></div>
169
+ </div>
170
+
171
+ </div>
172
+ </div>
173
+
174
+
175
+ <script type="text/plain" data-language="bash" data-title="toml">
176
+ ...
177
+
178
+ [settings]
179
+
180
+ [[settings.fields]]
181
+ type = "customer_reference"
182
+ </script>
183
+
184
+ </div>
185
+ </p>
186
+
187
+
188
+ You can use the following reference fields:
189
+
190
+ | Reference type (TOML) | Payload key | Description |
191
+ | --- | --- | --- |
192
+ | `customer_reference` | `customer_id` | The [`id`](/docs/api/admin-rest/current/resources/customer#resource-object) or [`legacyResourceId`](/docs/api/admin-graphql/current/objects/customer#field-customer-legacyresourceid) of the customer.<br><br>Triggers that include this property in the request body are also available to [Shopify marketing automations](/docs/apps/build/marketing-analytics/automations). |
193
+ | `order_reference` | `order_id` | The [`id`](/docs/api/admin-rest/current/resources/order#resource-object) or [`legacyResourceId`](/docs/api/admin-graphql/current/objects/order#field-order-legacyresourceid) of the order. |
194
+ | `product_reference` | `product_id` | The [`id`](/docs/api/admin-rest/current/resources/product#resource-object) or [`legacyResourceId`](/docs/api/admin-graphql/current/objects/product#field-product-legacyresourceid) of the product. |
195
+
196
+
197
+
198
+
199
+ When making a request to Flow, include the payload key. See the [mutation API reference section](#mutation-api-reference) for a complete example.
200
+
201
+ ### Custom field
202
+
203
+ A custom field lets you define the data that you send as part of your trigger request. The following is an example:
204
+
205
+ <p>
206
+ <div class="react-code-block" data-preset="file">
207
+ <div class="react-code-block-preload ThemeMode-dim">
208
+ <div class="react-code-block-preload-bar "></div>
209
+ <div class="react-code-block-preload-placeholder-container">
210
+ <div class="react-code-block-preload-code-container">
211
+ <div class="react-code-block-preload-codeline-number"></div>
212
+ <div class="react-code-block-preload-codeline"></div>
213
+ </div>
214
+ <div class="react-code-block-preload-code-container">
215
+ <div class="react-code-block-preload-codeline-number"></div>
216
+ <div class="react-code-block-preload-codeline"></div>
217
+ </div>
218
+ <div class="react-code-block-preload-code-container">
219
+ <div class="react-code-block-preload-codeline-number"></div>
220
+ <div class="react-code-block-preload-codeline"></div>
221
+ </div>
222
+ <div class="react-code-block-preload-code-container">
223
+ <div class="react-code-block-preload-codeline-number"></div>
224
+ <div class="react-code-block-preload-codeline"></div>
225
+ </div>
226
+ <div class="react-code-block-preload-code-container">
227
+ <div class="react-code-block-preload-codeline-number"></div>
228
+ <div class="react-code-block-preload-codeline"></div>
229
+ </div>
230
+ <div class="react-code-block-preload-code-container">
231
+ <div class="react-code-block-preload-codeline-number"></div>
232
+ <div class="react-code-block-preload-codeline"></div>
233
+ </div>
234
+ <div class="react-code-block-preload-code-container">
235
+ <div class="react-code-block-preload-codeline-number"></div>
236
+ <div class="react-code-block-preload-codeline"></div>
237
+ </div>
238
+
239
+ </div>
240
+ </div>
241
+
242
+
243
+ <script type="text/plain" data-language="bash" data-title="toml">
244
+ ...
245
+
246
+ [settings]
247
+
248
+ [[settings.fields]]
249
+ type = "number_decimal"
250
+ key = "Amount"
251
+ </script>
252
+
253
+ </div>
254
+ </p>
255
+
256
+
257
+ #### Custom field types
258
+
259
+ The following are the available custom field types:
260
+
261
+ | Field type | Description | Example |
262
+ | ----------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------- |
263
+ | `boolean` | A Boolean value. | `true`, `false` |
264
+ | `email` | An email formatted string. | `"[email protected]"` |
265
+ | `single_line_text_field` | A string. | `"Hello world."`
266
+ | `number_decimal` | A number with a decimal point. | `1.0` |
267
+ | `url` | A URL formatted string. | `"https://example/com"` |
268
+ | `schema.<type>` | `<type>` can be any type defined in the provided schema. [Learn more about defining complex types](/docs/apps/build/flow/configure-complex-data-types). | `{ "foo": "bar", "baz": 123 }` |
269
+
270
+ #### Naming custom fields
271
+
272
+ Field names need to be self-describing and readable. Use sentence case and separate words with spaces (not underscores or hyphens). These names can contain only alphabetical characters (a-z, A-Z) and spaces.
273
+
274
+ When you refer to these fields in the payload that you send to Shopify Flow, enter the names verbatim . For example, `{ "City location": "Ottawa" } }`. Don't use shortened versions.
275
+
276
+ #### Custom fields in the Shopify Flow editor
277
+
278
+ Fields can be used in the Shopify Flow editor either in conditions or in actions as [template variables](https://help.shopify.com/manual/shopify-plus/flow2/reference/variables). When used as template variables, Shopify Flow converts your `key` property to camelCase such as `{{ customerEmail }}`.
279
+
280
+ ## Mutation API reference
281
+
282
+ Once your extension is defined, published, and activated in a workflow according to [this guide](/docs/apps/build/flow/triggers/create), you can call Flow's mutation with an event, which will start the workflow(s).
283
+
284
+ ```graphql
285
+ mutation
286
+ {
287
+ flowTriggerReceive(
288
+ handle: "auction-bid-placed",
289
+ payload: {
290
+ "Amount": "30",
291
+ "customer_id": 12345
292
+ })
293
+ {
294
+ userErrors {field, message}
295
+ }
296
+ }
297
+ ```
298
+
299
+ | Property name | Property usage |
300
+ | ------------------- | ------------------------------------------------------------------------------------------------------ |
301
+ | `handle` | The extension’s handle. |
302
+ | `payload` | The fields that you selected for your payload schema in the action configuration. These should be serialized in a key-value pair format where the keys are equal to your field's “key” properties. |
303
+
304
+ > Note:
305
+ > If you are using a Shopify admin API version of `2023-07` or earlier the mutation won't support the `handle` and `payload` properties. For information on that mutation shape you can rely on the [flowTriggerReceive documentation](/docs/api/admin-graphql/2023-07/mutations/flowTriggerReceive).
306
+
307
+ ## Considerations
308
+
309
+ - When you create a trigger, the payload that you send to Shopify Flow needs to be [less than 1 MB and contain specific content](/docs/apps/build/flow/triggers/create#step-4-test-your-trigger) in the body.
310
+ - Triggers have the same [API rate limits](/docs/api/usage/rate-limits) as the Shopify API.
data/scraped/raw/shopify_dev/_docs_apps_build_flow.txt ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ [Shopify Flow](https://apps.shopify.com/flow) is an app that allows merchants to customize their store through automation. As a developer, you can integrate your app with the Flow platform through custom tasks, such as triggers and actions.
4
+
5
+ ![A workflow for a low stock notification displaying a trigger, condition, and action](/assets/apps/flow/example-workflow-inventory-quantity-changed.png)
6
+
7
+ This guide introduces you to the different extensions you can create, building a Flow trigger and action, and considerations when making changes to your extensions.
8
+
9
+ ## Why build for Flow
10
+
11
+ Building for Flow can help you to increase the value of your app by allowing merchants to automate their business processes. For example, suppose that you have a review app. After a review is created, merchants might want to send a notification (using email, Slack, or SMS), award loyalty points, and more. If you build the `Review created` trigger, Flow allows merchants to do any of those actions with your app. By integrating with Flow, you can:
12
+
13
+ - **Improve integrations between your app, Shopify, and other apps**: Any task you build can be used with the triggers and actions that Flow already provides, which immediately connects your app to thousands of new features.
14
+ - **Save development time**: Rather than building and maintaining direct integrations with many other apps, you can integrate with Flow and provide similar value to your merchants.
15
+ - **Improved visibility**: Merchants can discover your templates or tasks in Flow, even if they don't have your app installed. Additionally, when you integrate with Flow, you receive a **Works with Flow** badge on your listing in the Shopify App Store. Your app will also be listed in the [Flow app directory](https://apps.shopify.com/collections/connectors-for-shopify-flow).
16
+
17
+ ## What you can build
18
+
19
+ As a Partner you can build one or more tasks related to your app for your merchants to use. These merchants need to have both your app and Shopify Flow installed. Shopify Flow includes the following task types:
20
+
21
+ | Extension type | Description | Example |
22
+ |---|---|---|
23
+ | [Trigger](/docs/apps/build/flow/triggers) | An event that starts a workflow, and can be something that happens in a store or in an app. | A new order is created in a merchant's online store. |
24
+ | Condition | A rule that determines whether an action will be taken. As a developer you cannot create a condition task. | A condition is set to check whether the total amount paid for the order is over $200.00. |
25
+ | [Action](/docs/apps/build/flow/actions) | A task that's executed in a store or in an app when certain conditions are met. | If the total amount paid for the order is over $200.00, then a tag is added to the customer account that placed the order. |
26
+ | [Template](/docs/apps/build/flow/templates) | An example that demonstrates how your task works for a key use case. Templates are available through Flow's template library. | A workflow that sends an internal email when your trigger runs. |
27
+
28
+ ## Plans supported
29
+
30
+ Flow is an optional app that's available to Shopify merchants on any paid plan. Flow is widely adopted by Shopify merchants, especially those with stores on Shopify Plus.
31
+
32
+ Flow features [differ by plan](https://help.shopify.com/en/manual/shopify-flow). For apps, the primary difference is that if you have a [custom app](https://help.shopify.com/en/manual/apps/app-types/custom-apps), your Flow app extensions are available only to a [Shopify Plus](https://www.shopify.com/plus) store that has your app installed.
33
+
34
+ ## Templates
35
+
36
+ A template in Shopify Flow is an example workflow that can be copied into a merchant's shop. Templates help merchants automate a specific use case with minimal or no additional configuration. Flow's template library offers hundreds of templates with features to filter, browse, and search. You can [create a template](/docs/apps/build/flow/templates/create-a-template) for Shopify Flow that showcases your custom triggers and actions and help merchants do more.
37
+
38
+
39
+ ## Getting started
40
+
41
+ <div class="resource-card-grid">
42
+ <div>
43
+ <a class="resource-card" href="/docs/apps/build/flow/triggers" data-theme-mode="">
44
+ <div class="resource-card__indicator-container"><img
45
+ src="/assets/resource-cards/authentication"
46
+ data-alt-src="/assets/resource-cards/authentication-dark"
47
+ aria-hidden="true"
48
+ class="resource-card__icon themed-image"></div>
49
+ <h3 class="resource-card__title">
50
+ Learn more about triggers
51
+ </h3>
52
+ <p class="resource-card__description">Connect your app to Shopify Flow so that your app can send an event that starts a workflow.</p>
53
+ </a>
54
+ </div></p>
55
+
56
+ <p><div>
57
+ <a class="resource-card" href="/docs/apps/build/flow/actions" data-theme-mode="">
58
+ <div class="resource-card__indicator-container"><img
59
+ src="/assets/resource-cards/star"
60
+ data-alt-src="/assets/resource-cards/star-dark"
61
+ aria-hidden="true"
62
+ class="resource-card__icon themed-image"></div>
63
+ <h3 class="resource-card__title">
64
+ Learn more about actions
65
+ </h3>
66
+ <p class="resource-card__description">Connect your app to Shopify Flow so that your app receives data when a workflow action runs.</p>
67
+ </a>
68
+ </div></p>
69
+
70
+ <p><div>
71
+ <a class="resource-card" href="/docs/apps/build/flow/templates" data-theme-mode="">
72
+ <div class="resource-card__indicator-container"><img
73
+ src="/assets/resource-cards/filesystem"
74
+ data-alt-src="/assets/resource-cards/filesystem-dark"
75
+ aria-hidden="true"
76
+ class="resource-card__icon themed-image"></div>
77
+ <h3 class="resource-card__title">
78
+ Learn more about Flow templates
79
+ </h3>
80
+ <p class="resource-card__description">Create workflow templates to showcase your triggers and actions.</p>
81
+ </a>
82
+ </div></p>
83
+
84
+ <p><div>
85
+ <a class="resource-card" href="/docs/apps/build/flow/track-lifecycle-events" data-theme-mode="">
86
+ <div class="resource-card__indicator-container"><img
87
+ src="/assets/resource-cards/changelog"
88
+ data-alt-src="/assets/resource-cards/changelog-dark"
89
+ aria-hidden="true"
90
+ class="resource-card__icon themed-image"></div>
91
+ <h3 class="resource-card__title">
92
+ Lifecycle events
93
+ </h3>
94
+ <p class="resource-card__description">Get notified about events related to your Flow triggers and actions.</p>
95
+ </a>
96
+ </div></p>
97
+
98
+ <p><div>
99
+ <a class="resource-card" href="/docs/apps/build/flow/migrate-legacy-extensions" data-theme-mode="">
100
+ <div class="resource-card__indicator-container"><img
101
+ src="/assets/resource-cards/cli"
102
+ data-alt-src="/assets/resource-cards/cli-dark"
103
+ aria-hidden="true"
104
+ class="resource-card__icon themed-image"></div>
105
+ <h3 class="resource-card__title">
106
+ Migrate legacy Flow extensions
107
+ </h3>
108
+ <p class="resource-card__description">Learn how to migrate your existing extensions from the Partner Dashboard to CLI-managed.</p>
109
+ </a>
110
+ </div>
111
+ </div>
112
+
data/scraped/raw/shopify_dev/_docs_apps_build_flow_migrate-legacy-extensions.txt ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ If you have existing Flow extensions that were created through the Partner Dashboard, then you can import these extensions into your codebase. After you deploy the extensions that you’ve imported into Shopify CLI, Shopify CLI manages those extensions going forward.
4
+
5
+ > Note:
6
+ > Extensions that are migrated to Shopify CLI use the `handle` properties. The `handle` property is a unique string that identifies your extension and that's used when interacting with the Shopify Flow API. For more information, refer to the [triggers](/docs/apps/build/flow/triggers/create#step-4-test-your-trigger) and [actions](/docs/apps/build/flow/actions/endpoints#request) runtime payloads.
7
+
8
+ A `handle` property is created in the extension's TOML configuration file after running the import command. Note that you can't change the `handle` property of the extensions that are present in your app's codebase after you've run the `dev` or `deploy` commands.
9
+
10
+ ### Requirements
11
+
12
+ - Create a [Partner account](https://www.shopify.com/partners).
13
+ - [Scaffold an app that uses Shopify CLI v3.70.0 or higher](/docs/apps/build/scaffold-app), or [migrate your existing app](/docs/apps/build/cli-for-apps/migrate-to-latest-cli) so it's compatible with Shopify CLI v3.70.0 or higher.
14
+ - [Migrate a Partner Dashboard-managed app](/docs/apps/build/cli-for-apps/migrate-from-dashboard).
15
+ <br>
16
+
17
+
18
+ ## Step 1: Import your Flow task extension locally
19
+
20
+ > Note:
21
+ > The command in this procedure only generates the local file representation of your Partner Dashboard extensions. Running the `deploy` command migrates your extensions to CLI managed-extensions. You can only import extensions that have versions. The published version is imported, if one exists. Otherwise, the latest version is imported.
22
+
23
+ 1. Navigate to your app directory.
24
+ 1. To start importing your Flow extension, run the following command:
25
+
26
+ ```bash
27
+ #!/bin/bash
28
+ shopify app import-extensions
29
+ ```
30
+
31
+ 1. Select the `Flow Extensions` option.
32
+ 1. Select an extension from the list of extensions that are available to import.
33
+
34
+ After you’ve selected the extension to import, Shopify CLI automatically generates the file representation in your application’s `/extensions` directory and displays a success message.
35
+
36
+ You can then go into your application’s `/extensions` directory and start editing your extension. The file structure of your extension should look like the following:
37
+
38
+ ```text
39
+ /my-flow-extension
40
+ shopify.extension.toml
41
+ ```
42
+
43
+ To learn more about the extensions file structure, refer to [App structure](/docs/apps/build/cli-for-apps/app-structure) and the documentation for your extension type.
44
+
45
+ ### Available Flags
46
+
47
+ #### `client_id`
48
+
49
+ An application’s `client_id`. The ID enables you to target a specific application when running the import command.
50
+
51
+ ```bash
52
+ #!/bin/bash
53
+ shopify app import-extensions --client_id abc123
54
+ ```
55
+
56
+ ## Step 2: Migrate your extension
57
+
58
+ After you've imported the extension, you can migrate your extension by using Shopify CLI's `deploy` command.
59
+
60
+ > Note:
61
+ > Deploying extensions using the `app deploy` command also publishes the extensions. We recommend testing changes by using [`app dev`](/docs/api/shopify-cli/app/app-dev) or deploying to a test app before deploying them to a production app.
62
+
63
+ Use Shopify CLI to deploy your extensions:
64
+
65
+ 1. Navigate to your app directory.
66
+ 2. Run the following command to start deploying your extension(s):
67
+
68
+ ```bash
69
+ #!/bin/bash
70
+ shopify app deploy
71
+ ```
72
+
73
+ 3. Follow the prompts.
74
+
75
+ When you receive confirmation that the deploy was successful, your extensions have been released.
76
+
data/scraped/raw/shopify_dev/_docs_apps_build_flow_templates.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## How templates work
4
+
5
+ A template in Shopify Flow is an example workflow that can be copied into a merchant's shop. Templates help merchants automate a specific use case with minimal or no additional configuration. Flow's template library offers hundreds of templates with features to filter, browse, and search. You can [create a template](/docs/apps/build/flow/templates/create-a-template) for Shopify Flow that showcases your custom triggers and actions and help merchants do more.
6
+
7
+
8
+ ![Flow template library](/assets/apps/flow/flow-template-library.png)
9
+
10
+ ## Next steps
11
+ - Follow our step by step guide on [creating a Flow template](/docs/apps/build/flow/templates/create-a-template).
12
+ - Learn more about how localize your template, the approval process, and more in the [reference resource](/docs/apps/build/flow/templates/reference#approval-process)
data/scraped/raw/shopify_dev/_docs_apps_build_flow_track-lifecycle-events.txt ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ This guide explains how to configure your app to receive trigger lifecycle callbacks from Shopify Flow.
4
+
5
+ When [creating a trigger](/docs/apps/build/flow/triggers/create), configuring a lifecycle callback enables your app to receive notifications from Shopify Flow about stores using the trigger and communicate changes in workflow status (e.g., enabling or disabling a workflow) back to the app. This helps optimize app performance by ensuring that trigger-related operations are only performed for stores that actually need them.
6
+
7
+ Apps must be properly configured to respond to trigger lifecycle callbacks. When a merchant attempts to enable a workflow that uses the trigger, Shopify Flow sends a lifecycle callback to the app's web server. If it doesn't promptly receive a response or receives a response with an HTTP status code that isn't `2xx`, then the merchant can't enable the workflow and make use of the trigger.
8
+
9
+ > Note:
10
+ > Legacy trigger discovery webhook extensions created using the Partner Dashboard are deprecated and must [migrate to the CLI](docs/apps/build/flow/migrate-legacy-extensions) before they can be edited.
11
+
12
+ ## How trigger lifecycle callbacks work
13
+
14
+ Trigger lifecycle callbacks contain identifying information about the trigger and the store using it and indicate whether the trigger is being used. You can use this information to track the stores that are currently using your triggers and then send trigger requests to only those stores.
15
+
16
+ ### Properties
17
+
18
+ The trigger lifecycle callback (HTTP POST request) is formatted in JSON and it contains the following properties:
19
+
20
+ <table>
21
+ <tr>
22
+ <th>Property</th>
23
+ <th>Data type</th>
24
+ <th width="40%">Description</th>
25
+ <th>Example</th>
26
+ </tr>
27
+ <tr>
28
+ <td><code>flow_trigger_definition_id</code></td>
29
+ <td>String</td>
30
+ <td>The unique identifier for your Shopify Flow trigger.</td>
31
+ <td>Add row to spreadsheet</td>
32
+ </tr>
33
+ <tr>
34
+ <td><code>has_enabled_flow</code></td>
35
+ <td>Boolean</td>
36
+ <td>Whether the store has an enabled workflow that uses your trigger. Valid values:
37
+ <ul>
38
+ <li><code>true</code>: There is at least one workflow that is enabled and that uses your trigger.</li>
39
+ <li><code>false</code>: There are no enabled workflows that use your trigger.</li>
40
+ </ul>
41
+ </td>
42
+ <td>true</td>
43
+ </tr>
44
+ <tr>
45
+ <td><code>shop_id</code></td>
46
+ <td>Number</td>
47
+ <td>The unique identifier for the Shopify store.</td>
48
+ <td>690933842</td>
49
+ </tr>
50
+ <tr>
51
+ <td><code>shopify_domain</code></td>
52
+ <td>String</td>
53
+ <td>The myshopify domain of the Shopify store.</td>
54
+ <td>johnsapparel.myshopify.com</td>
55
+ </tr>
56
+ <tr>
57
+ <td><code>timestamp</code></td>
58
+ <td><a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a> date and timestamp</td>
59
+ <td>
60
+ <p>The time when the notification was created. Notifications with newer timestamps should take precedence. If you already have a timestamp in your datastore and you receive a newer timestamp, then overwrite this payload's information in your datastore. Conversely, if you receive a timestamp that is older than the information in your datastore, then ignore this payload.</p>
61
+ </td>
62
+ <td>2019-01-25T16:44:10.999Z</td>
63
+ </tr>
64
+ </table>
65
+
66
+ The following is an example body of a usage notification (HTTP POST) request:
67
+
68
+ ```json
69
+ {
70
+ "flow_trigger_definition_id": "Add row to spreadsheet",
71
+ "has_enabled_flow": false,
72
+ "shop_id": "690933842",
73
+ "shopify_domain": "johnapparel.myshopify.com",
74
+ "timestamp": "2019-01-25T16:44:10.999Z"
75
+ }
76
+ ```
77
+
78
+ ### Callback events
79
+
80
+ Shopify Flow sends trigger lifecycle callbacks when the following events occur:
81
+
82
+ - When a merchant activates a workflow that uses your trigger, the callback contains `"has_enabled_flow": true`.
83
+ - When a merchant deactivates a workflow that uses your trigger, the callback contains `"has_enabled_flow": false`.
84
+
85
+ ### Web server response time and status codes
86
+
87
+ When a merchant tries to enable a workflow that uses your trigger, Shopify Flow sends a trigger lifecycle callback to your web server. If your web server doesn't respond within five seconds, or if it responds with a different status code, then the merchant can't enable that workflow. The merchant receives a notification in the Shopify Flow app that tells them to try enabling the workflow at a later time.
88
+
89
+ ## 1. Configure your web server
90
+
91
+ To begin, configure your web server to listen for Shopify Flow callbacks.
92
+
93
+ 1. Configure a URL in your web server to listen for the trigger lifecycle callbacks from Shopify Flow.
94
+ 2. Configure your web server to verify the HMAC header in the trigger lifecycle callback with your client secret.
95
+
96
+ The HMAC header is located in the following HTTP header: `x-shopify-hmac-sha256`. If you are using a Ruby-based web framework, then the header is `http-x-shopify-hmac-sha256`.
97
+
98
+ 3. Configure your web server to respond within 5 seconds when it receives a trigger lifecycle callback.
99
+
100
+ ## 2. Process and store callback data
101
+
102
+ After you've added support to listen for Shopify Flow callbacks, you can configure your web server to process and store the callback data.
103
+
104
+ 1. Save the list of stores that are using your triggers in a persistent datastore. Use the <code>timestamp</code> property to make sure that you don't overwrite an existing entry with older information.
105
+ 2. Edit your application to send your triggers only to stores that are using your triggers.
106
+
107
+ ## 3. Configure the callback
108
+
109
+ Finally, configure the callback in the CLI:
110
+
111
+ 1. Run `shopify app generate extension`.
112
+ 2. Select `Flow trigger lifecycle callback`.
113
+ 3. Change the URL in the generated TOML to the URL configured on the web server.
114
+ 4. Run `shopify app deploy`.
115
+
116
+ ## Next steps
117
+
118
+ - Familiarize yourself with [Shopify Flow](/docs/apps/build/flow) and learn about building connectors.
119
+ - Connect your app to Shopify Flow so that events that occur in your app can [trigger workflows](/docs/apps/build/flow/triggers).
120
+ - Connect your app to Shopify Flow so that your app receives data and information when a [workflow action](/docs/apps/build/flow/actions) runs.
data/scraped/raw/shopify_dev/_docs_apps_build_flow_triggers.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ ## How triggers work
4
+
5
+ A trigger is a task in Shopify Flow that starts the execution of a workflow. The trigger represents an event that happens in a store or in an app. You can [build a trigger](/docs/apps/build/flow/triggers/create) for Shopify Flow so that events in your app trigger workflows to run.
6
+
7
+ ![A diagram that show how third party triggers interface with Flow ](/assets/apps/flow/trigger_diagram.png)
8
+
9
+ ## Next steps
10
+
11
+ - To build a trigger, you need to [create a trigger extension](/docs/apps/build/flow/triggers/create) in your app. In that extension, you specify details about the trigger using a [TOML file](/docs/apps/build/flow/triggers/reference).
12
+ - Once you have published your extension, you can then test or use it by [calling the Shopify API](/docs/apps/build/flow/triggers/reference#mutation-api-reference) with the trigger payload.
pyproject.toml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "shop-bot"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "aiohttp>=3.9.0",
9
+ "beautifulsoup4>=4.12.3",
10
+ "yarl>=1.9.4",
11
+ "aiodns>=3.1.1",
12
+ "aiosignal>=1.3.1",
13
+ "lxml>=5.1.0",
14
+ "langchain>=0.3.19",
15
+ "langchain-core>=0.3.37",
16
+ "langchain-community>=0.3.18",
17
+ "langchain-openai>=0.3.6",
18
+ "typing-extensions>=4.12.2",
19
+ "langgraph>=0.2.74",
20
+ "qdrant-client>=1.13.2",
21
+ "langchain-qdrant>=0.2.0",
22
+ "dotenv>=0.9.9",
23
+ "unstructured>=0.14.8",
24
+ "chainlit>=2.2.1",
25
+ ]
rag_graph.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+
3
+ from typing_extensions import List, TypedDict
4
+
5
+ from langchain_openai import ChatOpenAI, OpenAIEmbeddings
6
+
7
+ from langchain_core.documents import Document
8
+ from langchain_core.prompts import ChatPromptTemplate
9
+
10
+ from langchain_qdrant import QdrantVectorStore
11
+
12
+ from langgraph.graph import START, StateGraph
13
+ from langchain.prompts import ChatPromptTemplate
14
+ from langchain_community.document_loaders import DirectoryLoader
15
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
16
+
17
+ from qdrant_client.http.models import Distance, VectorParams
18
+
19
+ import nltk
20
+ nltk.download('punkt_tab')
21
+ nltk.download('averaged_perceptron_tagger_eng')
22
+
23
+ CHUNK_SIZE = 1000
24
+ CHUNK_OVERLAP = CHUNK_SIZE // 2
25
+
26
+ RAG_PROMPT = """\
27
+ You are a helpful assistant who answers questions based on provided context.
28
+ You must only use the provided context, and cannot use your own knowledge.
29
+
30
+ ### Question
31
+ {question}
32
+
33
+ ### Context
34
+ {context}
35
+ """
36
+
37
+ class RagGraph:
38
+ def __init__(self, qdrant_client):
39
+ self.llm = ChatOpenAI(model="gpt-4-turbo-preview", streaming=True)
40
+ self.collection_name = "rag_collection"
41
+ self.embeddings_model = OpenAIEmbeddings(model="text-embedding-3-small")
42
+ self.text_splitter = RecursiveCharacterTextSplitter(chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP)
43
+ self.rag_prompt = ChatPromptTemplate.from_template(RAG_PROMPT)
44
+ self.qdrant_client = qdrant_client
45
+
46
+ does_collection_exist = self.qdrant_client.collection_exists(collection_name=self.collection_name)
47
+
48
+ if not does_collection_exist:
49
+ qdrant_client.create_collection(
50
+ collection_name=self.collection_name,
51
+ vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
52
+ )
53
+
54
+ self.vector_store = QdrantVectorStore(
55
+ client=qdrant_client,
56
+ collection_name=self.collection_name,
57
+ embedding=self.embeddings_model,
58
+ )
59
+
60
+ if not does_collection_exist:
61
+ loader = DirectoryLoader("data/scraped/clean", glob="*.txt")
62
+ documents = self.text_splitter.split_documents(loader.load())
63
+ self.vector_store.add_documents(documents=documents)
64
+
65
+ self.vector_db_retriever = self.vector_store.as_retriever(search_kwargs={"k": 5})
66
+ self.graph = None
67
+
68
+ def create_rag_graph(self):
69
+ """Create the RAG graph."""
70
+ class State(TypedDict):
71
+ """State for the conversation."""
72
+ question: str
73
+ context: List[Document]
74
+
75
+ def retrieve(state):
76
+ question = state["question"]
77
+ retrieved_docs = self.vector_db_retriever.invoke(question)
78
+ return {"question": state["question"], "context": retrieved_docs}
79
+
80
+ async def stream(state):
81
+ """LangGraph node that streams responses"""
82
+ question = state["question"]
83
+ context = "\n\n".join(doc.page_content for doc in state["context"])
84
+ messages = self.rag_prompt.format_messages(question=question, context=context)
85
+ async for chunk in self.llm.astream(messages):
86
+ yield {"content": chunk.content}
87
+
88
+ graph_builder = StateGraph(State).add_sequence([retrieve, stream])
89
+ graph_builder.add_edge(START, "retrieve")
90
+ self.graph = graph_builder.compile()
91
+
92
+ def run(self, question):
93
+ """Run the graph."""
94
+ retrieved_docs = self.vector_db_retriever.invoke(question)
95
+ docs_content = "\n\n".join(doc.page_content for doc in retrieved_docs)
96
+ messages = self.rag_prompt.format_messages(question=question, context=docs_content)
97
+ response = self.llm.invoke(messages)
98
+
99
+ return {"response": response.content}
100
+
101
+ async def stream(self, question, msg):
102
+ """Stream the graph."""
103
+ async for event in self.graph.astream({"question": question, "context": []}, stream_mode=["messages"]):
104
+ _, (message_chunk, metadata) = event
105
+ if message_chunk.content:
106
+ await msg.stream_token(message_chunk.content)
107
+
108
+ await msg.send()
109
+
110
+ def main():
111
+ """Test the RAG graph."""
112
+ load_dotenv()
113
+ rag_graph = RagGraph()
114
+ # rag_graph.update_vector_store("data/scraped/clean", replace_documents=False)
115
+ rag_graph.create_rag_graph()
116
+ response = rag_graph.run("What is Shopify Flow?")
117
+ print(response["response"])
118
+
119
+ if __name__ == "__main__":
120
+ main()
scraper/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ """
2
+ Async web scraper for crawling documentation sites.
3
+ """
scraper/async_crawler.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ import asyncio
3
+ import logging
4
+ from pathlib import Path
5
+ from typing import Set, Dict
6
+ import aiohttp
7
+ from bs4 import BeautifulSoup
8
+ from yarl import URL
9
+ import json
10
+ import re
11
+
12
+ logging.basicConfig(level=logging.INFO)
13
+ logger = logging.getLogger(__name__)
14
+
15
+ class AsyncCrawler:
16
+ def __init__(self, start_url: str, max_concurrent: int = 100):
17
+ self.start_url = URL(start_url)
18
+ self.base_domain = self.start_url.host
19
+ self.base_path = str(self.start_url).split(self.base_domain)[1]
20
+ self.visited_urls: Set[str] = set()
21
+ self.url_queue: asyncio.Queue = asyncio.Queue()
22
+ self.semaphore = asyncio.Semaphore(max_concurrent)
23
+ self.session: aiohttp.ClientSession = None
24
+ self.data_dir = Path("data/scraped")
25
+ self.sitemap: Dict[str, list] = {}
26
+
27
+ async def init_session(self):
28
+ """Initialize aiohttp session with optimal settings."""
29
+ timeout = aiohttp.ClientTimeout(total=10)
30
+ connector = aiohttp.TCPConnector(limit=100, ttl_dns_cache=300)
31
+ self.session = aiohttp.ClientSession(
32
+ timeout=timeout,
33
+ connector=connector,
34
+ headers={"User-Agent": "ShopBot/1.0"}
35
+ )
36
+
37
+ def is_valid_url(self, url: URL) -> bool:
38
+ """Check if URL should be crawled."""
39
+ return (
40
+ str(url).startswith(str(self.start_url))
41
+ and url.scheme in ("http", "https")
42
+ and not url.fragment
43
+ )
44
+
45
+ async def process_page(self, url: str, html: str) -> Set[str]:
46
+ """Extract links and save raw HTML."""
47
+
48
+ # Regex pattern for Markdown links
49
+ pattern = r'\[.*?\]\((https?://[^\)]+|/[^)]+|[^\)]+)\)'
50
+
51
+ # Find all matches
52
+ markdown_links = re.findall(pattern, html)
53
+
54
+ soup = BeautifulSoup(html, 'html.parser')
55
+ anchor_links = [a['href'] for a in soup.find_all('a', href=True)]
56
+
57
+ links = markdown_links + anchor_links
58
+ absolute_links = [
59
+ str(URL(link)) if URL(link).host else str(self.start_url.join(URL(link)))
60
+ for link in links
61
+ ]
62
+
63
+ # concatenate the two sets
64
+
65
+ # Filter out invalid URLs
66
+ valid_links = {
67
+ link for link in absolute_links
68
+ if self.is_valid_url(URL
69
+ (link))
70
+ }
71
+
72
+ # Save raw HTML
73
+ # extract just the path from the url
74
+ path = url.split(self.base_domain)[1]
75
+
76
+ raw_filepath = self.data_dir / 'raw' / path.replace("/", "_").replace("_docs_apps_build_", "")
77
+ raw_filepath.parent.mkdir(parents=True, exist_ok=True)
78
+
79
+ raw_filepath.write_text(html)
80
+ # raw_filepath.write_text(self.strip_all_html_tags_from_markdown(html))
81
+
82
+ # Update sitemap
83
+ self.sitemap[url] = list(valid_links)
84
+
85
+ return valid_links
86
+
87
+ async def fetch_page(self, url: str) -> None:
88
+ """Fetch and process a single page."""
89
+ if url in self.visited_urls:
90
+ return
91
+
92
+ self.visited_urls.add(url)
93
+
94
+ try:
95
+ async with self.semaphore:
96
+ async with self.session.get(url) as response:
97
+ if response.status == 200:
98
+ html = await response.text()
99
+ new_urls = await self.process_page(url, html)
100
+
101
+ for new_url in new_urls:
102
+ if new_url not in self.visited_urls:
103
+ await self.url_queue.put(new_url)
104
+
105
+ logger.info(f"Successfully processed: {url}")
106
+ else:
107
+ logger.warning(f"Failed to fetch {url}: {response.status}")
108
+ except Exception as e:
109
+ logger.error(f"Error processing {url}: {str(e)}")
110
+
111
+ def strip_all_html_tags_from_markdown(self, markdown: str) -> str:
112
+ """Remove all HTML tags from a string, except for opening and closing script tags."""
113
+ # Define regex patterns to remove specific HTML tags
114
+ patterns = [
115
+ r'<div class="react-code-block" data-preset="file">\n',
116
+ r'<div class="react-code-block" data-preset="basic">\n',
117
+ r'<div class="react-code-block" data-preset="terminal">\n',
118
+ r'<div class="react-code-block-preload ThemeMode-dim">\n',
119
+ r'<div class="react-code-block-preload-bar "></div>\n',
120
+ r'<div class="react-code-block-preload-bar basic-codeblock">',
121
+ r'<div class="react-code-block-preload-placeholder-container">\n',
122
+ r'<div class="react-code-block-preload-code-container">\n',
123
+ r'<div class="react-code-block-preload-codeline-number"></div>\n',
124
+ r'<div class="react-code-block-preload-codeline"></div>\n',
125
+ r'<script data-option=[^>]+ data-value=[^>]+></script>\n',
126
+ r'<div>\n',
127
+ r'</div>\n',
128
+ r'<br>\n',
129
+ r'<p>\n',
130
+ r'</p>\n',
131
+ # r'<(?!script\b)[^>]+>',
132
+ # r'</(?!script\b)[^>]+>',
133
+ r'END_RAW_MD_CONTENT',
134
+ r'RAW_MD_CONTENT',
135
+ ]
136
+
137
+ # Remove all matched patterns from the markdown
138
+ for pattern in patterns:
139
+ markdown = re.sub(pattern, '', markdown)
140
+
141
+ markdown = re.sub(r'<script type="text/plain"[^>]+language="([^"]+)"[^>]*>', r'```\1', markdown)
142
+ markdown = re.sub(r'</script>', '```', markdown)
143
+
144
+ # replace 3 or more new lines with 2 new lines
145
+ markdown = re.sub(r'\n{3,}', '\n\n', markdown)
146
+
147
+ return markdown
148
+
149
+ def clean_raw_markdown(self):
150
+ """Clean raw markdown files by stripping HTML tags."""
151
+ raw_dir = self.data_dir / 'raw'
152
+ for raw_file in raw_dir.glob('*.txt'):
153
+ content = raw_file.read_text()
154
+ cleaned_content = self.strip_all_html_tags_from_markdown(content)
155
+
156
+ raw_filepath = self.data_dir / 'clean' / raw_file.name
157
+ raw_filepath.parent.mkdir(parents=True, exist_ok=True)
158
+ raw_filepath.write_text(cleaned_content)
159
+
160
+ async def run(self):
161
+ """Main crawler execution."""
162
+ # Create data directory
163
+ self.data_dir.mkdir(parents=True, exist_ok=True)
164
+
165
+ await self.init_session()
166
+ await self.url_queue.put(str(self.start_url))
167
+
168
+ try:
169
+ workers = []
170
+ while True:
171
+
172
+ if self.url_queue.empty() and not workers:
173
+ break
174
+
175
+ while not self.url_queue.empty():
176
+ url = await self.url_queue.get() + '.txt'
177
+
178
+ if url not in self.visited_urls:
179
+ worker = asyncio.create_task(self.fetch_page(url))
180
+ workers.append(worker)
181
+
182
+ if workers:
183
+ done, pending = await asyncio.wait(
184
+ workers,
185
+ return_when=asyncio.FIRST_COMPLETED
186
+ )
187
+ workers = list(pending)
188
+ for task in done:
189
+ await task
190
+ finally:
191
+ # Save sitemap
192
+ sitemap_path = self.data_dir / "_sitemap.json"
193
+ sitemap_path.write_text(json.dumps(self.sitemap, indent=2))
194
+ self.clean_raw_markdown()
195
+
196
+ await self.session.close()
197
+ logger.info(f"Crawl completed. Processed {len(self.visited_urls)} pages.")
198
+
199
+ async def main():
200
+ start_url = "https://shopify.dev/docs/apps/build/flow"
201
+ crawler = AsyncCrawler(start_url)
202
+ await crawler.run()
203
+
204
+ if __name__ == "__main__":
205
+ asyncio.run(main())
uv.lock ADDED
The diff for this file is too large to render. See raw diff