flutter_seo 1.1.1 flutter_seo: ^1.1.1 copied to clipboard
Flutter SEO package
Features #
You can use the flutter_seo package to add tags to your html, which you can use to try SEO optimization.
My web site with flutter_seo package.
On the site made with the sample below, you can see that meta data is added to the head and html tag is created on the body.
https://seo-package-sample.web.app/
Usage #
1. Add Head Tag
If you want to add a description tag, please refer to below.
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(
(timeStamp) {
HeadTagUtil.add("name", "description", "Add description");
HeadTagUtil.add("property", "og:url", "Add og:url");
},
);
super.initState();
}
2. Add head Title
HeadTagUtil.setTitle("titleName");
3. If you want to add several pre-defined tags, follow along
void addMetaTag() {
WidgetsBinding.instance.addPostFrameCallback(
(timeStamp) {
HeadTagUtil.setTitle("flutter_seo title");
},
);
HeadTagUtil.add("name", "keywords", "flutter, web, seo");
HeadTagUtil.setHead(
title: "Check title",
keywords: ["111", "222", "333", "444"],
description: "Check description",
imageUrl:
"https://sailing-it-images.s3.ap-northeast-2.amazonaws.com/logo.png",
url: "https://sailing-it.com",
);
}
4. Add body tag
In order to add body tags, you must add the desired SeoKey to the widget.
Then call CreateHtml.makeWidgetTree(context)
when the widget is drawn
class SecondScreen extends StatefulWidget {
const SecondScreen({super.key});
@override
State<SecondScreen> createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(
(timeStamp) {
HeadTagUtil.setTitle("SecondScreen");
CreateHtml.makeWidgetTree(context);
},
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: SeoKey(TagType.div),
appBar: AppBar(
title: const Text("Second Screen"),
),
body: Column(
children: [
Container(
key: SeoKey(TagType.div),
),
Text(
"second",
key: SeoKey(TagType.p, text: "second"),
),
],
),
);
}
}
5. Use Navigator's then to draw html again after pop.
void movePage(BuildContext context, Widget widget, String currentTitle) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => widget),
).then(
(value) {
HeadTagUtil.setTitle(currentTitle);
CreateHtml.makeWidgetTree(context);
},
);
}
Example #
Follow the example below to add tags.
to /example
folder.
import 'package:flutter/material.dart';
import 'package:flutter_seo/flutter_seo.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const FirstScreen(),
);
}
void addMetaTag() {
HeadTagUtil.setHead(
title: "Check title",
keywords: [
"flutter_seo",
"flutter",
"flutter element",
"flutter web seo"
],
description: "Check description",
imageUrl:
"https://sailing-it-images.s3.ap-northeast-2.amazonaws.com/logo.png",
url: "https://sailing-it.com",
);
}
}
void movePage(BuildContext context, Widget widget, String currentTitle) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => widget),
).then(
(value) {
HeadTagUtil.setTitle(currentTitle);
CreateHtml.makeWidgetTree(context);
},
);
}
class FirstScreen extends StatefulWidget {
const FirstScreen({super.key});
@override
State<FirstScreen> createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(
(timeStamp) {
HeadTagUtil.setTitle("FirstScreen");
CreateHtml.makeWidgetTree(context);
},
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Column(
key: SeoKey(TagType.div),
children: [
SizedBox(
key: SeoKey(TagType.nav),
child: Row(
key: SeoKey(TagType.ul),
children: [
ElevatedButton(
key: SeoKey(TagType.li),
onPressed: () {
movePage(context, const SecondScreen(), "FirstScreen");
},
child: Text(
key: SeoKey(TagType.a,
src: '#secondScreen', text: "secondScreen"),
"go secondScreen"),
),
],
),
),
Column(
key: SeoKey(
TagType.div,
attributes: const {"customStyle": "custom attributes"},
),
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"header text h1",
key: SeoKey(TagType.h1, text: "header text h1"),
),
Text(
"header text h2",
key: SeoKey(TagType.h2, text: "header text h2"),
),
Column(
key: SeoKey(TagType.div),
children: [
Text("Check 3", key: SeoKey(TagType.p)),
Row(
key: SeoKey(TagType.div),
children: [
Text("Check 4", key: SeoKey(TagType.p)),
Text("Check 8", key: SeoKey(TagType.p)),
SizedBox(
key: SeoKey(TagType.div),
child: Stack(
key: SeoKey(TagType.div),
children: [
Text("Check 9", key: SeoKey(TagType.p)),
Text("Check 10", key: SeoKey(TagType.p)),
],
),
)
],
),
],
),
Text("Check P", key: SeoKey(TagType.p)),
Container(
key: SeoKey(
TagType.a,
src: "a tag",
text: "Check String a tag",
),
child: Text("Check String a tag", key: SeoKey(TagType.p)),
),
SizedBox(
key: SeoKey(TagType.a,
src: "assets/company_device.png", text: "Local image"),
width: 200,
height: 200,
child: Image.asset(
key: SeoKey(
TagType.img,
src: "assets/company_device.png",
alt: "Local image",
),
"assets/company_device.png",
fit: BoxFit.cover,
),
),
const SizedBox(height: 20),
SizedBox(
key: SeoKey(
TagType.a,
src:
"https://sailing-it-images.s3.ap-northeast-2.amazonaws.com/logo.png",
),
width: 200,
height: 200,
child: Image.network(
key: SeoKey(
TagType.img,
src:
"https://sailing-it-images.s3.ap-northeast-2.amazonaws.com/logo.png",
alt: "Network Image",
),
"https://sailing-it-images.s3.ap-northeast-2.amazonaws.com/logo.png",
fit: BoxFit.cover,
),
),
],
),
Column(
key: SeoKey(TagType.footer),
children: [
Text("Check 5", key: SeoKey(TagType.p)),
Text("Check 6", key: SeoKey(TagType.p)),
],
),
],
),
),
),
);
}
}
class SecondScreen extends StatefulWidget {
const SecondScreen({super.key});
@override
State<SecondScreen> createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(
(timeStamp) {
HeadTagUtil.setTitle("SecondScreen");
CreateHtml.makeWidgetTree(context);
},
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: SeoKey(TagType.div),
appBar: AppBar(
title: const Text("Second Screen"),
),
body: Column(
children: [
Container(
key: SeoKey(TagType.div),
),
Text(
"second",
key: SeoKey(TagType.p, text: "second"),
),
ElevatedButton(
onPressed: () {
HeadTagUtil.removeByValue("robots");
},
child: const Text("Remove head")) ,
ElevatedButton(
onPressed: () {
HeadTagUtil.add("name", "description", "Update description");
},
child: const Text("Change Head")) ,
],
),
);
}
}